<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>


html第一天

<body>
    <strong>加粗</strong> <b>加粗</b><br> 最常用的是 strong
    <em>倾斜</em> <i>倾斜</i><br> 最常用的是i
    <del>删除线</del><s>删除线</s><br> 不重要
    <ins>下划线</ins><u>下划线</u><br> 不重要
    <div>块级标签</div> 重点,行级标签可以独占一行
    <span>行内标签</span> 块级标签同行可以放多个,不能居中
    <img src="" alt=""> 插入图片,在src里放图片路径,"./"列出当前列表内容,"../列出上一级内容"
    <a href="">链接</a> 链接,在href里写链接跳转的地址(路径),两个a括号之间写链接显示名字
    <a href="#12">锚点链接</a> 锚点链接,可以跳转到网页的某一处,在href里写 "#id",再在目的地那行写上"id= "
    &emsp;是全角空格,占据宽度正好是一个中文字体的宽度,基本不受字体变化影响
    &nbsp;半角空格,受字体影响较大
    &ensp;大概二分之一字体大小,基本不受字体影响

    <header>：头部标签
        <nav>：导航标签
            <article>：内容标签
                <section>：定义文档某个区域
                    <aside>：侧边栏标签
                        <footer>：尾部标签
</body>





html第二天

<body>
    base target="_blank"设置整个页面的链接开启方式为打开一个新窗口,此命令写在head当中
    <!-- 表格边框做法 
    给表格左上分别加上边框,再给td th加右下边框-->
    table {
    font-size: 20px;
    flex: 1;
    border-top: 1px solid #fff;
    border-left: 1px solid #fff;
    border-spacing: 0;
    border-radius: 0.208rem;

    th,
    td {
    height: 32px;
    text-align: center;
    border-bottom: 1px solid #fff;
    border-right: 1px solid #fff;
    }
    }
    <!-- 表格 -->
    <table>表格
        <caption>表格的标题标签</caption><br>
        caption只跟表格搭配使用,可以居中
        <tr>生成于表格的一行
            <th>内容</th>填写文字的地方,写一个th就是一格标题,加粗居中
            <th>内容</th>填写文字的地方,写一个th就是一格标题,加粗居中
        </tr>
        <tr>
            <td>内容</td>填写文字的地方
            <td>内容</td>填写文字的地方
        </tr>
    </table>

    <!-- 列表 -->
    <ul>无序列表
        <li>内容</li>无序列表格,排列出来的前面有个点(可取消)
        <li>内容</li>无序列表格,排列出来的前面有个点(可取消)
    </ul>
    <ol>有序列表
        <li>内容</li>有序列表格,排列出来前面自带数字
        <li>内容</li>有序列表格,排列出来前面自带数字
    </ol>
    <dl>自定义列表
        <dt>标题</dt>自定义列表标题
        <dd>内容</dd>自定义列表内容
    </dl>

    <!-- 表单域 -->
    <input type="range">滚动条
    <input type="text">text输入框,单标签
    <input type="password"> password密码框,输入时隐藏密码
    <input type="radio" name="xxx"> radio单选,相同name的只能选择一个
    <input type="radio" name="xxx" checked> checked,进入网页时自动默认选中
    <input type="checkbox" name="xxx"> checkbox多选,相同name的可以多选
    <input type="text" placeholder="未输入时默认显示的内容"> placeholder未输入时默认显示的内容
    <label for="id"> </label>
    <id="#" 要联动的图片或者文字>增加用户体验,点同一个id 的label设置的图文可联动
        <input type="button" value="普通按钮"><br> 点了也不会提交,后期配合js使用
        <input type="submit" value="提交按钮"><br>submit是提交按钮,要配合form表单域使用
        <input type="image" src="imges/sub-btn.jpg"><br>image是图片按钮,必须要有src属性来找图片位置,也要配合form表单域提交
        <button>点击按钮</button>button是双标签,可以直接提交
        <textarea placeholder="文本域"></textarea> textarea是一个文本域,用来显示文字/
        <select>下拉列表
            <option>1</option>下拉内容
            <option>2</option>下拉内容
            <option>3</option>下拉内容
        </select>

        <!-- input状态 -->
        readonly 只读
        disabled 禁用输入框无法获取
        hidden 隐藏
        checked 默认选中
</body>




css第一天

<body>
    <!-- 选择器 -->
    d {
    直接对网页中的标签指令进行操作
    }
    .xxx {
    ".xxx" 类选择器,最常用,在需要改动的标签中写入"class='xxx'",然后在style中写入.xxx再写命令
    }
    #xxxx{
    为id选择器,配合id="xxxx"使用,只可以使用一次,后期配合js使
    }

    /* 文字设置 */
    color 文字颜色
    font-family:"微软雅黑" 是设置字体
    font-size:16px 设置字体大小,一般为12 15 16 20
    font-weight: 设置字体粗细,400为正常,700为粗
    font-style:normel 可以将倾斜的字体回正,变为正的字体(图案)
    font-style:italic 设置字体或图为倾斜
    font: "是否斜体" '是否加粗' "字体高度/上下间距" "字体设置"
    text-align: center;居中操作,只限于行级标签,选中父元素,操作子元素

    /* 下划线 */
    text-decoration: none; none 取消下划线,适用于a链接
    text-decoration: underline; 增加下划线

    /* 缩进 */
    text-indent:2em 自动缩进, em是一个字的宽度,2em就是自动缩进2个字宽
    line-height:36px 行间距,字体+上下间距的像素距离

    /* 外部样式表 重点!!!! */
    <link rel="stylesheet" href="xxxxx.css">外部样式表调用,将使用的css文件位置写入 href,即可引入本网页,之后在要使用的标签里写上class="xxxxx"
</body>





css第二天

<body>

    <!-- emmet语法 -->

    <!-- .class 直接生成class,默认div-->
    <div class="class">哈哈哈哈哈</div>
    <!-- 想要生成带class的其他标签,需要 p.class -->
    <p class="class"><a href="#145">asdasd asd </a></p>
    <!-- 并列关系 .gege+.didi  -->
    <div class="gege"></div>
    <div class="didi"></div>
    <!-- 嵌套关系 ul>li*3>a -->
    <!-- 哪个要几对,就*几 -->

    <!-- 后代选择器 -->
    .cc li {}
    /* 后代选择器,以路径控制所要控制的标签 */

    <!-- 并集选择器 -->
    h1,
    h2,
    h3,
    h4,
    h5,
    h6
    /* 并集选择器可以将多个元素选中,同时下指令,每个元素用逗号隔开 */

    <!-- 鼠标经过 -->
    a:hover{}

    <!-- 元素分类 -->
    一 块级元素
    块级元素:div p h ul li 等等 -->
    1.可以独占一行
    2.可以设置宽度高度
    3.默认宽度是父级元素的宽度
    4.块级元素可以包含任何元素
    特殊情况:p和h不能包含块级元素,其他的不影响

    二 行内元素
    行内元素:span strong em 等等
    1.一行显示多个
    2.不能设置宽度高度
    3.默认宽度是内容的宽度
    4.行内元素只能包含行内元素
    特殊情况:a链接不可以放a链接
    a链接里可以放块级元素

    <!-- 模式转换 -->
    display: inline-block;
    display: inline-block;可以把行内元素转变为块级元素,但是还是可以同一行显示
    display: block; 可以把行内元素变为块级元素,就像一个div,独占一行

    <!-- 背景图片 -->
    background-image: url(./images/bg1.png);
    <!-- background-rgba (0.0.0.1) 透明度 -->
    <!-- /* background-image: url(图片地址);背景图片 */ -->
    background-repeat: no-repeat;
    <!-- /* background-repeat: no-repeat;不平铺 */ -->
    <!-- /* background-repeat: repeat-x;横向平铺 */ -->
    <!-- /* background-repeat: repeat-y;纵向平铺 */ -->
    background-position: right bottom;
    <!-- /* background-position: 设置背景图片的位置,只写一个默认下一个为center居中 -->
    <!-- 纵向: top上 center中 bottom下 -->
    <!-- 水平: left左 center中 right右*/ -->
</body>






css第三天

<body>
    <!-- 层叠性 -->
    相同的属性命令有变化,取最近的
    <!-- 继承性 -->
    在自己本身未加属性的情况下,会继承父级的属性,但是权重会为零
    <!-- 权重 -->
    在加过属性的不同命令中,按权重计算哪个生效,
    (0.0.0.0) 优先度为 行内元素 >id >类class >标签> 自己的属性> 继承>
    权重高的才会生效,权重低的会被覆盖,(行内样式.id.class.标签) 通配符 浏览器默认 继承 */
    !important,权重无限大
    <!-- 边框 -->
    border-top: 2px red solid;
    实线 solid实线
    虚线 dashed虚线
    点线 dotted点线
    <!-- 内边距 -->
    padding:20px 代表盒子内边距向内 四个方向 收缩20px
    不同的方向:上top 右 right 下bottom 左left
    <!-- 外边距 -->
    margin:20px 代表盒子外边距向外 四个方向 撑大20px
    auto可以让左右填充满 例: margin:0 auto;
    外边距上下使用margin,外边距不会相加,会取最大值
    外边距左右不会取最大值,会相加
    <!-- 塌陷问题 -->
    overfloe:hidden（也可以用作溢出隐藏）
    当块级元素嵌套关系时,给子元素设margin-top,会带着父元素一起下降,这时候可以给父元素设置 overfloe:hidden
    <!-- 盒子阴影 -->
    box-shadow: 13px 15px 17px 2px rgb(0 0 0 / 50%);
    box-shadow: x位置 y位置 模糊度 阴影尺寸 阴影颜色
    <!-- 圆角 -->
    border-radius: 20px;
    border-radius: 20px;是倒圆角, 20就是半径
</body>








css第四天

<body>
    <!-- 浮动 -->
    float left 靠左浮动,right靠右浮动
    1.浮动只会和相邻的浮动元素一起生效
    2.浮动元素之间如果不相邻,那中间未被浮动的块级元素会独占一行,后边的浮动元素就会被挤到未被浮动元素下边进行浮动
    3.浮动起来之后,之后的元素会在底层被覆盖显示,所以一般在浮动的元素外会再套一个块级元素
    4.在浮动元素套上父级块级元素时候,此时后面的和父级元素同级的块级元素不会在底层覆盖显示,因为父级元素独占一行,同级只能被挤到下一行显示
    <!-- 清除浮动 -->
    overflow:hidden 还可以溢出隐藏
    clear: both
    <!-- 隐藏元素 -->
    visibility: hidden;
</body>








css第六天

<body>
    <!-- 定位 -->
    相对定位 绝对定位 固定定位

    <!-- 相对定位 -->
    position: relative;
    相对定位: 相对于自己的位置移动
    保留位置，还是标准流

    <!-- 绝对定位 -->
    position: absolute;
    1.绝对定位移动的位置为当前页面的位置
    2.父元素只有加上除了静态定位以外的定位才能框柱
    3.绝对定位不占位置

    <!-- 子绝父相 -->
    子绝父相 子元素为绝对定位,父元素就要将其框柱,若同样用绝对,那么内容就不占位置,下面的内容就会升上来,所以要用相对定位占位置

    <!-- 固定定位 -->
    position: fixed;
    以浏览器为准不受盒子限制,上下滑动也固定在一个位置,脱离标准流
</body>








css第七天

<body>
    <!-- 元素隐藏 -->
    display: none; 隐藏元素,且不占位置
    display: block; 元素显示
    配合hover可以实现隐藏显示图片

    <!-- 精灵图 -->
    background: url(./images/abcd.jpg) no-repeat -387px -141px;
    选择图片 并且选定位置 例-387px -141px

    <!-- 字体图标 -->
    css中要有字体的地址,之后在字体图标的位置要表明字体
    例: font-family:'iconfont';

    如果已经link了字体文件,那可以直接加<i class='class字体名字  iconfont'></i>>

    <!-- 鼠标指针图标 -->
    <li style="cursor: default;"> default 默认箭头</li>
    <li style="cursor: pointer;"> pointer 手指箭头</li>
    <li style="cursor: text;"> text 文本箭头</li>
    <li style="cursor: move;"> move 移动箭头</li>
    <li style="cursor: not-allowed;"> no-allowed 禁止图标</li>

    <!-- 图片文字对齐 -->
    vertical-align: middle;
    中线对齐,防止给字母预留基线空间上

</body>








css第八天

<body>
    <!-- 视频标签 -->
    <video src="./video/01-logo.mp4" width="500px" controls muted poster="../css02/images/大蛇丸.jpg" loop></video>
    src 视频路径
    controls 视频播放控件
    autoplay 自动播放 google是自动播放,但是加了muted可以静音播放
    loop循环播放
    poster 视频第一帧,封面

    <!-- 属性选择器 -->
    以bo 开头的全选中 div[class^=bo]{}
    以x 结尾的全选中 div[class$=x]
    class等于的类名全选中 div[class=box1]

    <!-- 结构选择器 -->
    给最后一个加属性
    .dad li:last-child{}

    给第一个加属性
    .dad li:first-child{}

    给第几个加属性
    .dad li:nth-child(数字)
    数字可以写 n ,就代表所有的数字
    10n 就是10*n,就是每10个加属性
    -n+5就是选中前五个
    n+5选中从第五个开始之后所有的

    偶数 2n
    奇数 2n+1

    <!-- 伪元素 -->
    .类 :伪类 ::伪元素
    伪元素是通过css添加进来的 实际上不在存在在dom树上的
    伪元素添加进来的是一个行内元素

    必须添加centen

    li::before{ centen:'' }
    在li 的最开始添加内容
    li::after{ centen:'' }
    在li 的最后添加内容

    <!-- 过渡 -->
    在hover里添加要变的属性,只能是数值类
    之后在变动属性添加transition,控制时间
    transition: 300ms;





    <!-- 网站图标 -->
    <link rel="shortcut icon" href="图标路径" />
</body>








H5C3第一天

<body>
    <!-- 移动 -->
    /* transform: translate(x,y,z) */
    /* 移动,和相对定位类似,移动后保留位置 */

    <!-- 旋转 -->
    transform: rotate(360deg);
    要先写移动,在写旋转,旋转单位为deg,意为 度


    <!-- 圆心 -->
    transform-origin: -100% 50%;
    确定旋转的圆心坐标,可以用left,centerd或者百分数以及具体像素值

    <!-- 动画 -->
    /* animation:
    name(动画名称)
    duration(动画时间) 单位为s
    timing-function(运动曲线) 默认是ease,匀速是linear
    delay(延时何时开始) 单位为秒
    iteration-count(动画执行次数) 无单位,无限次为infinite
    direction(是否在下一周期逆向播放) alternate
    fill-mode(结束时停留在); 最终位置forwards backwards回到起点
    */

    @keyframes name {
    100%{}
    }
    在元素中调用 name以使用动画

</body>







H5C3第二天

<body>
    <!-- 3D Z轴移动-->
    transform: translateZ(900px)
    代表向外升起900px,正常看不到,需要在父元素加上透视

    <!-- 3D 旋转 -->
    transform: rotateY(360deg);
    可以确定旋转轴,不设置轴默认为Z轴

    <!-- 透视 -->
    transform-style: preserve-3d;
    加上之后可以显示Z轴变化的效果

    <!-- 设置元素被查看距离 -->
    perspective: 400px;

</body>








移动web第一天

<body>
    <!-- 改变内容为弹性容器布局-->
    display: flex;

    <!-- 改变主轴方向为垂直 可以将元素垂直放置 -->
    flex-direction: column;

    <!-- 翻转布局方向,从右往左放置 -->
    /* flex-direction: row-reverse; */

    <!-- /* 主轴对齐方式 */ -->
    /* justify-content: ; */

    居中显示
    justify-content: center;

    盒子左右
    每个盒子的左右边距一样,效果为盒子间距是盒子到父级边框间距两倍
    justify-content: space-around;

    盒子之间
    只是盒子间距一样,不包括父级边框
    /justify-content: space-between;

    /* 所有的间距均分,都一样 */
    justify-content: space-evenly;


    <!-- 侧轴对齐方式 -->
    侧轴
    align-items: ;

    侧轴居中
    align-items: center;

    侧轴子元素的高度拉伸为父元素高度,要将子元素高度去除
    align-items: stretch;

    调整弹性盒子内行对齐的对齐方式 (行间距)
    align-content:
    space-around
    space-between;
    space-evenly

    宽度不够的时候自动换行显示
    flex-wrap: wrap;


    <!-- 伸缩比 -->
    flex 表示将父元素剩余宽度分份,然后按份分剩余宽度
    加在子元素上
</body>








移动web第二天

<body>
    <!-- 视口 -->
    使用meta标签设置视口宽度，适配不同设备宽度的网页
    name="viewport" content="width=s, initial-scale=1.0"
    viewport：视口
    width=device-width：视口宽度 = 设备宽度
    initial-scale=1.0：缩放1倍（不缩放）

    <!-- 分辨率 -->
    物理分辨率
    生产屏幕时就固定的，它是不可被改变的
    逻辑分辨率是 软件（驱动）决定的

    一般设计稿都是w375,这时候一般是以苹果6/7/8的逻辑分辨率为准做的
    写页面是要以逻辑分辨率为准,看图要X2

    <!-- 流式布局 -->
    宽度： 百分比
    高度： 固定
</body>












移动web第三天

<body>
    <!-- rem 布局 -->
    根据视口变化,使网页元素同时自适应改变大小
    1个rem 等于1个html字体尺寸



    <!-- 阿里开源字体自适应js -->
    此js将rem设置为视口的十分之一
    <script src="./js/flexible.js"></script>


    <!-- less语法 -->
    是css的一种拓展语法,不可以直接被html文件直接调用,需要保存生成css文件,然后调用

    <!-- 计算 -->
    width: (68px/37.5rem)
    width: 68px+2rem
    加减乘直接写对应的符号
    除法要加上小括号 也可以 ./
    单位为第一个单位

    <!-- 变量 -->
    先定义变量名
    @color: cyan;
    在要使用的元素调用变量
    background-color: @color;
    需要改的话直接改变量,网页多个调用可以同时改变


    和页面尺寸计算配合为
    @rootfontsize:37.5rem;
    .x { width:(尺寸/37.5) }


    <!-- 嵌套 -->

    .box {
    width: 100px;
    height: 100px;
    background-color: cyan;

    // 后代选择器
    .son {
    width: 20px;
    height: 20px;
    background-color: #666;
    }


    // 伪类选择器 &代替父级类名
    &:hover {
    background-color: rgb(221, 221, 221);
    }
    }

    <!-- 导入 -->
    导入文件
    @import url(./05-less计算.less);
    引号情况下,less文件可以不加后缀
    @import './06-less变量';


    <!-- 导出 禁止导出 -->
    // out:./
    // 导出 第一行out : 导出保存路径


    // 第一行禁止导出
    // out:false

    // 修改所有导出路径
    // 在设置中搜索easyless,在setting.json中编辑添加一段代码 "out":"保存路径"
    // !!注意!! 所有setting.json中的代码都要加双引号

    <!-- 混合写法 -->
    // 混合使用
    .box2 {
    .box ();
    }


    <!-- 混合高级 -->
    @bd1: 1px;
    @bd2: 2px;

    .border (@sdfasd) {
    border-top: @sdfasd solid cyan;
    }

    .box1 {
    .border(@bd1)
    }

    .box2 {
    .border(@bd2)
    }

</body>










移动web第四天

<body>
    <!-- 响应式布局 -->
    一套代码适用于多种视口终端,改变视口尺寸的时候,页面元素的布局尺寸随之改变
    多用于企业网站,适合简洁的网站




    <!-- 媒体查询  -->
    限制样式生效条件,如下就是最大宽为1000最小宽为800之间,样式生效
    @media (min-width:800px) and (max-width:1000px) {
    body {
    background-color: cyan;
    }
    }

    <!-- 完整写法 -->
    /* @media screen and (max-width:768px) {
    body {
    background-color: pink;
    }
    } */

    /* and () and () */
    /* 768-992之间 */
    @media (min-width:768px) and (max-width:992px) {
    body {
    background-color:green;
    }
    }


    <!-- 外链响应布局 -->
    <link rel="stylesheet" href="./one.css" media="(min-width:800px)">

</body>









bootstrap框架

<body>
    <!-- bootstrap框架 -->
    bootstrap框架是 tuiter 公开的框架,里面规定了全局样式,组件,JS插件可以直接调用,不用背,需要的时候去找

    需要添加或更改样式,部分可以直接在class里添加类名


    <!-- 重点要记的 -->
    .container
    container类自带间距15px;
    版心作用 自带padding margin 默认宽度为1200px

    .row
    row类自带间距-15px

    container-fluid
    不设置宽高 自带padding margin
    占满一行,左右留边距

    <!-- 栅格系统 -->
    将整个网页的宽度分成 几 等份,之后按照视口尺寸变化,内容自适应根据栅格份数进行缩放

    bootstrap3将视口尺寸分为12份
    响应断点为四个
    col-xs-* 超小屏幕 小于768px
    col-sm-* 小屏幕 大于768px小于998px
    col-md-* 中等屏幕
    col-lg-* 大屏幕
    *为所占栅格份数


    <!-- bootstrap调用 -->
    全局CSS样式 组件 js插件
    需要的时候通过右侧目录查找,复制粘贴然后改变需要添加的关键名词

    <!-- !!!!源码修改!!!! -->
    !!!!重点!!!!
    1.首先在bootstrap文件夹中找到名为variables的less文件
    2.打开之后在需要更改的地方搜索,然后更改样式
    3.之后返回顶部,写入 // out:false,main:bootstrap.css
    4.在link 的bootstrap文件里找到bootstrap.css,然后将刚刚生成的文件进行替换覆盖,之后在link中改变文件为此文件

</body>










JavaScript第一天

<body>
    <script>
        // < !--输入输出 -->
        数字不用引号, 其他的都要引号
        js读取顺序是从上到下读取

        // < !--输入 -->
        // < !--弹窗内容 -->
        alert('显示内容')
        // < !--输入框!!!!重点!!!! -- >
        prompt('请输入密码')
        // < !--确认 取消键-- >
        confirm('确定要删除吗')

        // < !--输出 -->
        // < !--body内容 -->
        document.write('body的内容')
        // < !--控制台内容!!!!重点!!!! -- >
        console.log('控制台显示的内容')




        // < !--变量写法 -->
        // < !--第一种 -->
        let nub1
        nub1 = 1
        console.log(nub1)
        // < !--第二种 -->
        let nub2 = 2
        console.log(nub2)
        // < !--连写 -->
        let nub3 = 3, nub4 = 4, nub5 = 5
        console.log(nub3, nub4, nub5)




        // < !--注意事项 -->
        // < !--变量名 -->
        1.只能由 下划线 英文 数字 $ 组成, 不能以数字开头
        2.不能用关键字, 如 let log 等
        3.严格区分大小写, 如 Abc 和 abc是两个变量
        建议: 有意义的起名, 驼峰命名, 第二个词首字母大写




        // < !--变量交换 -->
        1.建立一个临时中转变量 并将nub1放入临时变量
        2.将nub2放入nub1中
        3.将临时变量中的数据放入nub2中





        // < !--变量计算 -->
        let nub1 = 10, nub2 = 5, nub3 = 3
        console.log(nub1 + nub2)
        console.log(nub1 - nub2)
        console.log(nub1 * nub2)
        console.log(nub1 / nub2)
        console.log(nub1 % nub3)//取模 取余数
        有括号先算括号
        console.log((nub1 + nub2) / nub3)






        // < !--数据类型 -->

        typeof 判断的元素
        typeof 1 // number

        判断的元素 instanceof 目标类型 返回一个布尔值
        arr instanceof Arra; // true
        date instanceof Date; // true
        fn instanceof Function; // true
        Object.prototype.toString.call()

        判断的元素.contructor
        arr.constructor === Array; //true
        date.constructor === Date; //true
        fn.constructor === Function; //true




        // 区分数组和对象
        1. Array.isArray(判断的元素)
        // 数组返回true 对象返回false

        2. 判断元素 instanceof Array
        // 数组返回true 对象返回false

        3. 判断的元素.contructor
        // 数组返回 ƒ Array()  { [native code] }
        // 对象返回 ƒ Object() { [native code] }

        4. Object.prototype.toString.call(ary)
        // 数组返回 [object Array]
        // 对象返回 [object Object]




        共分四种数据类型
        1.数字类型      number
        2.字符串类型    string
        3.未定义        undefined
        4.布尔型        boolean

        1.number 数字类型 不带引号的数值
        let nub1 = 1
        2.string 字符串类型 带引号的内容
        let nub2 = '1'
        3.undefined 未定义 未定义此变量的内容
        let nub3
        4.boolean 布尔型, 判断真假
        let nub4 = true / false



        // < !--字符串拼接 -->两种方法
        第一种
        console.log('我叫' + name + ', 今年' + nianling + '岁')

        第二种 模板拼接, 更提倡用这种方法
        console.log(`我叫${变量名},今年${变量名}岁`)
        内容用``括住, 变量用${ } 括起来




        // < !--数据类型转换 -->
        两种方法
        // 第一种 显式转换
        // 数字转字符串
        1.console.log(变量名.toString())
        console.log(nub4.toString())
        2.let nub1 = new String(nub2)
        console.log(nub1)

        // 字符串转数字
        数字以外不能转换
        三种方法
        Number()
        原样转换为数字
        console.log(Number(nub1), Number(nub2));
        parseInt()
        去除小数部分
        console.log(parseInt(nub1), parseInt(nub2))
        parseFloat()
        保留小数转换
        console.log(parseFloat(nub1), parseFloat(nub2));

        // 第二种 隐式转换  
        //字符串转数字
        let nub10 = +prompt('请输入数字')
        let nub20 = +prompt('请输入数字')
        在prompt前加 + 号, 意为正号, 会自动将字符串转为数字, 计算也可以直接将字符串转为数字然后计算
        console.log(nub10 - nub20)
        let nub11 = prompt('请输入数字')
        let nub22 = prompt('请输入数字')
        let nub33 = nub11 - nub22
    </script>


</body>









JavaScript第二天

<body>
    <script>
        // < !--函数 -->


        //封装函数
        niubi()// 可以在定义前就调用   
        function niubi() {// 封装函数/定义函数  function            
            alert('哈哈哈哈')// 被封装的代码
        }
        niubi()// 调用运行函数


        // 断点调试
        1.打开控制台, 选择sources
        2.选中要测试的文件
        3.选中开始运行的一行代码, 单击行号, 打断点
        4.刷新浏览器
        5.选中右边的箭头


        // 参数     
        // 形参 实参
        function num(qwe, ewq) { // (qwe, ewq)是赋予括号里未知数的灵活性,可以被调用时进行指定
            document.write(qwe + ewq)
        }
        num(6, 7)
        // 形参
        // (qwe, ewq)是形参  不是真实的数据,等待调用时接收指定的数据
        // 实参
        // num(6,7)是实参   是真实的数据,可以赋值给形参里的未知数任何数字



        // 函数案例
        简单 例:
        let name = prompt('请输入你的名字')
        let money = prompt('请输入你的余额')
        function jieshao(a, b) {
            document.write(`我叫${a},我银行卡里有${b}万元`)
        }
        jieshao(name, money)
        计算 例:
        let yue = prompt('请输入银行卡余额')
        let xiaofei = prompt('请输入本次消费金额')
        let you = prompt('请输入路程往返油费')
        function money(z, x, c) {
            return z - x - c
        }
        let qian = money(yue, xiaofei, you)
        document.write(`经过本次消费,您的卡内余额还有${qian}元,欢迎下次消费`)
        多个计算 例:
        let miao = prompt('输入秒数')
        function time(x) {
            let h = parseInt(x / 60 / 60)
            let m = parseInt(x / 60 % 60)
            let s = parseInt(x % 60)
            document.write(`${x}秒转化为${h}小时${m}分钟${s}秒`)
        }
        time(miao)


        // 函数返回值
        return 属性名
        //将函数中return的内容返到调用函数的地方, 之后查询调用函数的时候可以查出内容或直接调用
        例:
        function a() {
            let cc = 1 + 1
            console.log(cc)
            return cc
        }
        console.log(a())
        console.log(a() - 2)







        // 对象
        // 空对象:
        let obj1 = {}
        let obj1 = null
        // 当未来有变量需要存储的数据是对象型,但是现在还没有任何数据的时候,提前预留空对象



        // 有数据对象
        内容写键值对, 加: 和, 可以写多个属性名
        let aaa = {
            name: 'zjy',
            age: '21',
            xingbie: '男'
        }
        console.log(aaa)
        console.log(typeof aaa)


        // 对象属性的访问
        //第一种    对象名.属性名
        console.log(aaa.name);
        //第二种    对象名['属性名'] 或者 对象名[新的变量名](新的变量名和对象的内容相同不需要加引号,直接加新的变量名)
        console.log(aaa['name']);
        let bbb = 'name'
        console.log(aaa[bbb]);


        // 对象属性的更改
        // 修改变量
        // 第一种 对象名.变量名=值
        aaa.name = 'jia'
        console.log(aaa.name);
        // 第二种 对象名['变量名']
        aaa['age'] = 18
        console.log(aaa['age']);
        // 第三种 选一个没有的变量名,会生成一个新的键值对
        aaa.xingbie = 'man'
        console.log(aaa.xingbie);





        // 方法
        // 写在对象里的函数叫做方法
        例:
        let asd = {
            // 以下就是方法
            say: function () {
                console.log('我会说话');
            }
        }
        // 调用时   对象名.方法名()
        asd.say()
        // 添加新的方法   对象名.方法名 = function() {}
        asd.eat = function () {
            console.log('我会吃');
        }



    </script>

</body>









JavaScript第三天

<body>
    <script>
        // Math 语法

        // Math内置
        console.log(Math);
        // 随机0到1之间所有的数
        console.log(Math.random());
        // 括号后面跟*几 就是在0到几之间随机
        console.log(Math.random() * 5);
        // 向上取整 小数进一
        console.log(Math.ceil(5.5));
        // 向下取整 去掉小数
        console.log(Math.floor(5.5));
        // 四舍五入
        console.log(Math.round(3.1)); // 3
        console.log(Math.round(3.6)); // 4
        // 取两个数的最大最小值
        Math.min(x, y)//最小
        Math.max(x, y)//最大
        // 算 N 到 M 的整数
        console.log(Math.floor * (N - M + 1) + N);

        // x 的 y 次幂
        Math.pow(8, 2)  // 64





        // 比较运算符
        //  == 双等号   只判断数值是否相等 相等true 不等false
        console.log(3 == '3');
        // === 全等   先判断数值类型是否一样,再判断数值是否相等 有一样不同即为fales
        console.log(3 === '3');
        // !== 是否不相等       
        console.log(3 !== '4')
        // 字符串判断   每个字符也有定义的默认大小,但是不重要
        console.log('a' < 'c');
        // isNaN  ()      判断是否不是数字 不是数字为true
        console.log(isNaN('a'));




        // 逻辑运算符
        // 与 &&    都真才真
        // 表示元素要同时为 true 结果才为 true ,有任何一个为false 结果都为false    
        console.log(3 > 1 && 5 > 2);//true
        console.log(3 < 1 && 5 > 2);//false

        // 或 ||    一真则真
        // 表示元素任意一个为 true 结果就为 true ,都为fales,结果为fales
        console.log(3 < 1 || 5 > 2);//true
        console.log(3 < 1 || 5 < 2);//false

        //非 !      
        // 表示相反的判断
        console.log(!(3 < 1));//true
        console.log(!(3 > 1));//false




        // 短路
        // 条件不赋值 算false
        // 在 && 中,只要左边为false,则后边的程序不执行,直接判断为false    反之则输出最后的程序结果    
        // 在 || 中,只要左边为true,则后边的程序不执行,直接判断为true      反之则输出最后的程序结果
        function zxc(x, y) {
            x = x || 6
            y = y || 3
            console.log(x + y);
        }
        zxc()





        // if!!!重点!!!!
        // if 分为：单分支、双分支、多分支
        // 单分支就是只写一个if
        // 双分支就是多写一个else
        // 多分支就是写好几个else   

        // 括号内的条件为true时，进入大括号里执行代码
        // 小括号内的结果若不是布尔类型时，会发生隐式转换转为布尔类型


        // 多分枝不能打乱顺序,满足第一个if就不会执行后边的代码
        let zxc = prompt('想来网吧,先输入你的年龄:')
        // if ( 判断条件 ) 为true才会执行
        if (zxc >= 18) {
            // 执行的属性
            alert('电子海洛因,吸到手抽筋');

        } else if (zxc < 18 && zxc > 6) {//当前面的if没有执行,就会顺位到此再进行判断,为true就可执行本段代码,也可不写条件直接执行
            alert('滚,回家做作业去');
        } else {
            alert('给爷爬回家吃奶去')
        }





        // switch语句
        // if和switch的内容都可以互相做到,但是if要简洁好用很多
        let goods = prompt('请输入您想搜索的产品')
        switch (goods) {
            // 找到跟小括号里数据全等的case值，并执行里面对应的代码
            case '手机':
                alert('小米 苹果 华为 三星')
                // break表示一个case到此结束
                break
            // 数据若跟'电脑'全等，则执行代码2
            case '电脑':
                alert('外星人 玩家国度 宏碁')
                break
        }



        // switch 穿透效果
        // 穿透效果 就是不写break,可以节省代码量
        let num = +prompt('请输入查询的月份')
        switch (num) {
            case 3:
            case 4:
            case 5:
                alert('春天')
                break
            case 6:
            case 7:
            case 8:
                alert('夏天')
                break
            case 9:
            case 10:
            case 11:
                alert('秋天')
                break
            case 12:
            case 1:
            case 2:
                alert('冬天')
                break
        }


        // 三元表达式
        // 仅限于 真假都是只有一种情况可以使用
        let year = prompt('大爷来玩啊')
        // ?后跟着 true 的执行代码 
        // :后跟着 false 的执行代码
        year >= 18 ? alert('这是飞一样的感觉') : alert('腿给你打断')
        let years = confirm('大爷来玩啊')
    </script>
</body>








JavaScript第四天

<body>
    <script>
        // 赋值运算符
        let num = 1
        num += 5    //num为6
        //  num += 5 表示 num = num * 5 , 表示先将num进行计算,再重新赋值给自己, + - * / % 都可以用



        // 一元运算 自加一
        // num++
        // 后置自增,如果同行有计算或判断,同行执行时还是原数,执行之后再 + 1
        // ++num
        // 前置自增,直接将自己 + 1


        // while循环
        // 在...条件中 执行代码
        // 三要素
        // 1.给变量初始值
        // 2.终止条件   
        // 3.条件自增自减   
        let i = 1
        while (i <= 100) {
            document.write('螺旋丸' + '<br>')
            i++
        }



        // do while 语法
        // 因为 while在 do下边,所以不管真假代码都会执行一次,了解就好
        let i = 1
        let num = 0
        do {
            num += i
            i++
        } while (i <= 100)
        document.write(num)



        // for循环
        // 和while循环差不多,只是更适合计算数据,如果循环内没有输出,则在外部调用的 i 变量是最后循环结束的值
        // for (初始; 终止条件; 自增;) { }
        for (i = 1; i <= 50; i++) {
            document.write('真想当个废物' + '<br>')
        }

        // for 嵌套
        // 将内循环完全执行完毕, 再回外循环进行变量自增
        for (let i = 1; i <= 3; i++) {
            document.write('咳咳(清嗓子)<br>')
            for (let j = 1; j <= 3; j++) {
                document.write('磨剪子嘞戗菜刀<br>')
            }
            document.write('<br>')
        }



        // 循环结束
        // break    就此打断,后面的代码不执行结束循环
        // continue  跳过此次程序,执行下次的代码
        for (let i = 1; i <= 10; i++) {
            if (i % 3 == 0) {
                console.log('吃第三个饱了, 后面的不吃了');
                // break    就此打断,后面的代码不执行结束循环
                break
            }
            console.log(i);
        }

        for (let i = 1; i <= 10; i++) {
            if (i % 3 == 0) {
                console.log('哎妈呀, 大虫子, 这个不吃了, 没吃饱, 4和5 照常吃');
                // continue  跳过此程序,执行下面的代码
                continue
            }
            console.log(i);
        }
    </script>
</body>








JavaScript第五天

<body>
    <script>
        // 数组
        // 1.数组查找
        // name[1]  数组名 [索引值]     
        // 索引值从0开始, 如: 劫为0,男刀为1,狐狸为2
        console.log(name[2]);



        // 2.数组修改
        name[1] = '流浪'
        console.log(name[1]);



        // 3.length 属性    数组长度(数据数量) 语法: 对象名.属性
        console.log(name.length);




        // 遍历
        // 配合for,列出所有内容的索引值,然后根据索引列出内容
        for (i = 0; i < name.length; i++)
            // 对象遍历方法
            // let 变量名 in 对象名
            for (let i in lol) {
                // 列出所有内容
                document.write(lol[i]);
                // 添加 'huli'的对象
                document.write(lol.huli);
            }




        // 封装函数数组组合使用 三案例
        // 直接封装
        function getsum() {
            let num = [1, 2, 3, 4, 5, 6, 7]
            let sum = 0
            for (i = 0; i < num.length; i++) {
                sum += num[i]
            }
            // 和
            console.log(sum);
            // 平均
            console.log(sum / num.length);
        }
        getsum()
        // 参数修改数值封装
        function getsum(x) {
            let sum = 0
            for (i = 0; i < x.length; i++) {
                sum += x[i]
            }
            console.log(sum);
        }
        getsum([1, 2, 3, 4, 5, 6, 7])
        getsum([1, 2, 3, 4])
        console.log('哈哈哈哈哈');
        getsum([4, 5, 6, 7])
        getsum([5, 6, 7])
        getsum([1, 2, 5, 6, 7])
        getsum([1, 2])
        // 在外边log  有多个结果可以在封装函数里将结果组成数组,在外部调用的时候,用return返回,之后可以选择调用的索引值
        function getsum(x) {
            let sum = 0
            for (i = 0; i < x.length; i++) {
                sum += x[i]
            }
            let ave = sum / x.length
            return [sum, ave]
        }
        let he = getsum([1, 2, 3, 4, 5, 6, 7])
        console.log(he[0]);





        // 随机点名并删除案例
        let name = ['劫', '男刀', '光头', '狐狸']
        let index = Math.floor(Math.random() * name.length)
        console.log(name[index]);
        name.splice(index, 1)
        console.log(name);






        // 数组最大值案例
        let num = [5, 55, 33, 22, 88, 99, 77, 44, 66, 11]
        let max = num[0]
        for (let i = 0; i < num.length; i++) {
            if (max < num[i]) {
                max = num[i]
            }

        }
        console.log(max);
    </script>
</body>







webAPI 第一天

<body>
    <script>
        // DOM
        概念: 文档对象模型-- -> 将html文档封装成一个document对象
        作用: 方便通过js操作网页

        // 获得标签对象

        // 通过id获取标签
        let abc = document.getElementById(1)
        console.log(abc);
        语法 document.getElementById(id名)
        返回值 返回的就是当前的标签对象
        // 获得body标签对象
        // 语法:    document.body
        let a = document.body
        console.log(a);
        // 获得html标签对象
        // 语法:    document.documentElement
        let b = document.documentElement
        console.log(b);


        // 通过id获取操作图片
        // 首先获取图片标签对象
        let myimg = document.getElementById('img')
        // 然后赋予标签src路径
        myimg.src = './images/b03.jpg'



        // css样式
        // 修改背景图
        // 获取背景图对象
        let a = document.getElementById('d')
        // 找到背景图css地址,然后赋值
        // 语法" 标签对象.style css属性='值'
        a.style.background = 'cyan'



        // 给非表单标签设置文字内容
        // 语法1: 标签对象.innerText = 值;
        // 语法2: 标签对象.innerHTML = 值;
        // 代码演示:语法1: 标签对象.innerText = 值;
        let div = document.getElementById('one');
        div.innerText = '<h1>我是通过js方式设置的文字</h1>';
        div.innerHTML = '<h1>我是通过js方式设置的文字</h1>';
        // 1.通过innerText给标签设置文字内容的时候,不管是普通的文字还是html标签,最后都是以文字的形式设置给标签
        // 2.通过innerHTML给标签设置文字内容的时候,如果遇到html标签,则可以渲染成真正的html标签

        // 修改表单,加等号
        .value     获取表单文本内容
            .value = 修改 表单文本内容
                // 修改非表单,也是加等号
                .innerText 只能显示纯文字
                    .innerhtml 可以显示标签



        // 倒计时 案例
        // 1.倒计时需要两个时间 现在的时间,未来的时间
        // 2.需要两个时间以时间戳的形式做差
        // 3.做差之后将 以毫秒为单位的 数字转化为秒数
        // 4.以秒数为准,分别计算 天,时,分,秒
        // 5.最后将字符串拼接显示在网页中
        // d = parseInt(总秒数 / 60 / 60 / 24)  //  计算天数
        // h = parseInt(总秒数 / 60 / 60 % 24)  //   计算小时
        // m = parseInt(总秒数 / 60 % 60);      //计算分数
        // s = parseInt(总秒数 % 60);           //计算秒数
        function daojishi() {
            let time = +new Date()
            let overtime = +new Date('2021-6-1 12:00:00')
            let num = overtime - time
            console.log(num);
            times = num / 1000
            let d = parseInt(times / 60 / 60 / 24)  //天数
            let h = parseInt(times / 60 / 60 % 24)  //小时
            let m = parseInt(times / 60 % 60)       //分钟
            let s = parseInt(times % 60)            //秒
            let h1 = document.getElementById('zxc')
            h1.innerText = `距离毕业还有${d}天${h}时${m}分${s}秒`
            return h1
        }
        daojishi()
        setInterval(daojishi, 1000)




        // 定时器 
        // 代码隔一段时间 执行一次
        // 语法: setInterval(函数名, 毫秒)
        setInterval(daojishi, 1000)
    </script>
</body>







webAPI 第二天

<body>
    <script>
        // 停止定时器
        //clearInterval(定时器ID);
        //setInterval()的返回值就是定时器ID
        let b = setInterval(a, 500)
        clearInterval(b)


        // 表单控件不可选中
        input.disabled
        赋值为true, 可以正常显示
        赋值为false, 表单控件不可点击


        // 注册事件
        // 点击类型 click
        // 注册事件三个要素:  事件源 + 事件类型 + function(){} 处理程序
        // 事件源: 就是一个具体的标签对象
        // 事件类型: 代表的用户动作   click (用户的点击动作)
        // 处理程序fuction(){}:  执行事件中对应的代码
        // 语法: 事件源.addEventListener('事件类型', function(){})
        // 注意:
        // 1. 注册事件的时候,必须是一个具体的标签对象
        // 2. 如果得到的结果是一个数组,数组中有标签对象,那么必须先遍历数组,然后注册事件
        button.addEventListener('click', function () {
            alert('唔系古天乐,唔系渣渣辉,是兄弟就来砍我')
        })



        // 获取元素的方式
        // ☞ 获取单个标签(只能获取一个标签)
        document.querySelector()        //获取单个 css选择器 的标签
        document.getElementById()       //获取单个 ID 的标签
        // ☞ 获取多个标签,返回值都是数组
        document.querySelectorAll()     //获取所有相同 css选择器 的标签
        document.getElementsByTagName() //获取所有同一个 HTML标签名 的标签
        // ☞ 获取固定的标签
        document.body                   //获取body
        document.documentElement        //获取HTML




        // 操作元素样式
        给标签设置 行内样式 可以用 style
        给标签设置 类样式 可以用 className  具有覆盖性, 相当于将类名赋予给标签, 赋予什么, 标签的类就只有什么
        给标签设置 类样式 可以用 classList  添加类名, 不会将原有的类覆盖掉


        // 通过style设置行内样式  
        // 语法:  标签对象.style.css属性 = 值
        div.style.backgrand = 'cyan'

        // ☞ 通过className设置类样式
        // 语法:  标签对象.className = '类名  类名'
        a[i].className = 'box'  //样式为 box
        div.className = ''      //为空则取消所有class




        // 排他思想: 干掉所有的标签,给当前对应的标签设置样式
        // 利用for循环得到所有的标签
        // 然后将遍历后的标签样式清除
        // 在清除后再在需要添加的元素上添加样式
        // 相当于带着复活甲去自爆
    </script>
</body>







webAPI 第三天

<body>
    <script>
        // this 
        1.在程序中调用方法(函数), this指向调用者(谁调用this就指向谁)
        2.在程序中谁调用方法(函数), 那么this就指向谁(this就是谁)



        // 自定义属性
        //应用场景: 网页中tab栏切换效果
        //建立一个新的属性标签,用以存储数据或字符.

        // dataset方式
        //设置自定义属性语法 
        //标签对象.dataset.自定义属性名 = 值
        //转变的样式为 <div data-hero = 'one' ></div >
        let div = document.querySelector('div')
        div.dataset.hero = 'one'
        // 获取自定义属性方法为 
        // 标签对象.dataset.自定义属性名
        div.dataset.hero

        // 通过 setAttribute() /  getAttribute()
        // 除了可以设置自定义属性,还可以设置获取标准属性
        // 设置
        标签对象.setAttribute('data-自定义属性', 值)
        // 获取
        标签对象.getAttribute('data-自定义属性')




        // 注册事件
        // DOM L0
        // 语法 标签对象.on事件类型 = function () { }
        1. 本质上就是将一个函数赋值给一个属性
        2. 因为是一个属性, 所以会被覆盖, 所以只能有一个封装函数

        // DOM L1
        // 语法 标签对象.addEventListener('事件类型', function () { })
        1. 本质上就是调用了一个方法
        2. 同一种事件类型可以注册多次



        // 移除事件
        // 移除DOML0事件
        // 标签对象.on事件类型 = null
        btn.onclick = function () {
            console.log('123123');
        }
        btn2.onclick = function () {
            btn1.onclick = null
        }
        // 移除DOML1事件
        // 注册事件的时候必须单独定义一个函数
        // 标签对象.removeEventListener('事件类型', 函数名)
        function fn() {
            console.log(55555);
        }
        btn.addEventListener('click', fn)
        btn2.addEventListener('click', function () {
            btn.removeEventListener('click', fn)
        })




        // 鼠标事件类型
        click        单击
        dblclick     双击
        mouseenter   鼠标进入事件   mouseover
        mouseleave   鼠标离开事件   mouseout
        mousemove    鼠标移动事件
        dragover     鼠标进入事件源, 未抬起按键时
        drop         鼠标进入事件源, 松开时
        mousedown    鼠标按下事件
        mouseup      鼠标抬起事件


        // 获取鼠标位置
        offsetX     相对当前事件源
        clientX     相对于页面(不包括滚动条)
        pageX       相对于页面(包括滚动条)
        screenY     相对于整个屏幕



        // 事件对象参数
        // 在事件中设置一个参数,该参数叫事件对象参数
        // 例:  c 这个形参就是事件对象参数
        let div = document.querySelector('div')
        div.onclick = function (c) {
            console.log(c.clientX);
        }



        // 函数的各种叫法
        // 具名函数
        // 有函数名叫具名函数
        // 匿名函数
        // 没有函数名叫匿名函数
        // 高阶函数
        // 也是一个函数
        // 特点
        // 参数是函数
        // 定时器就是一个典型的高阶函数
        // 回调函数
        // 在高阶函数中, 表示参数的函数称为回调函数
        // 定时器中表示参数的函数叫回调函数
        // 自调用函数(自执行函数)
        // 函数自己调用自己
        // 语法: (函数体)()
    </script>
</body>









webAPI 第四天

<body>
    <script>
        // 创建元素: document.createElement('html标签名')
        let h1 = document.createElement('h1')
        // 返回: 返回当前创建的标签对象



        // 添加元素
        // 添加到父元素的末尾:           appendChild    
        // 语法: 父元素标签对象.appendChild(创建的标签对象)
        let ul = document.createElement('ul')
        body.appendChild(ul)
        ul.appendChild(li)
        //添加到父元素中任意的位置:     insertBefore 
        // 语法: 父元素标签对象.insertBefore(创建的标签对象, 目标元素)
        let ul = document.createElement('ul')
        body.appendChild(ul)
        ul.appendChild(li)



        // 删除元素
        // 父元素标签对象.removeChild(要被移除的元素)
        body.removeChild(h1)



        // 获取父级元素
        // 语法: 父元素标签对象.parentNode
        let p = document.querySelector('p')
        console.log(p.parentNode);

        // 获取子级元素
        // 语法:  子元素标签对象.children
        获取多个, 以数组形式输出.children
        let ul = document.querySelector('ul')
        console.log(ul.children);


        // 兄弟元素
        // 下一个同级标签
        // 标签对象.nextElementSibling
        h1.nextElementSibling
        // 上一个同级标签
        // 标签对象.previousElementSibling
        h1.previousElementSibling





        // 事件流:  在嵌套结构中发生事件流现象
        // ☞ 事件捕获: 在嵌套结构中,事件从父元素(外)向子元素(内)传递
        // 处于目标阶段
        // ☞ 事件冒泡: 在嵌套结构中,事件从子元素(内)向父元素(外)传递
        // 注意: 
        // 1. 如果要看到事件捕获现象---> 注册事件的时候,必须使用 addEventListener
        // 2. addEventListener 第三个参数必须设置为true
        // ☞ 通过 事件对象参数.stopPropagation() 阻止事件冒泡



        // 委托思想: 本应该自己完成的事情(注册事件),交给父元素注册事件
        // 将点击的工作交给父级元素(减少代码量)
        // 事件对象参数.target     
        // 相当于在事件源范围内,点哪哪反应,配合其他的标签或指令可以划定生效范围
        例: 加 innerText 就是生效范围为文字
        let ul = document.querySelector('ul')
        ul.onclick = function (a) {
            console.log(a.target.innerText);
        }
        例: 加.parentNode 就是范围限定为两级父元素之内
        thead.onclick = function (cc) {
            let del = cc.target.parentNode.parentNode
            thead.removeChild(del)
        }



        // 用户输入事件: input事件
        //  用户输入就会执行该事件, 给表单元素注册



        //获取内容长度: 内容.length 
        let str = 'adsfafafadadfadfaf';
        console.log(str.length);
    </script>
</body>











webAPI 第五天

<body>
    <script>
        // load事件: 资源加载
        1. 当将js代码写到head标签标签中(将js代码写到html标签前面), 就要使用load事件
        2. 给window注册load事件
        3. 当要网页中的所有标签都加载完成后(渲染完成后)才会执行load事件
        4. 如果将js代码写到html标签后面, 则load事件可以加也可以不用加
        // 例:
        window.onload = function () {
            let div = document.querySelector('div');
            console.log(div);
        }



        // 滚动事件: 拖拽滚动条的时候,触发滚动事件 scroll事件
        // 步骤
        // ☞ 必须要保证页面有滚动条(垂直方向)
        // ☞ 给window注册滚动事件
        window.addEventListener('scroll', function () {
            console.log(123);
        })
        // 在滚动事件中获取页面滚动的距离 .scrollTop
        // 语法: document.documentElement.scrollTop
        window.addEventListener('scroll', function () {
            let res = document.documentElement.scrollTop;
        });
        // 滚动返回顶部案例:
        let btn = document.querySelector('.box')
        window.onscroll = function () {
            let lg = document.documentElement.scrollTop
            if (lg >= 2000) {
                btn.style.display = 'block'
            } else {
                btn.style.display = 'none'
            }
        }
        btn.onclick = function () {
            document.documentElement.scrollTop = 0
        }




        // 获取元素的大小
        标签对象.offsetWidth   获取元素实际宽度 = 内容区域 + 左右内边距 + 左右边框
        标签对象.offsetHeight  获取元素实际高度 = 内容区域 + 内边距 + 边框

        标签对象.clientWidth   获取元素宽度 = 内容区域 + 左右内边距
        标签对象.clientHeight  获取元素高度 = 内容区域 + 内边距

        标签对象.clientLeft    获取元素的左边框
        标签对象.clientTop     获取元素的上边框

        右边边框 = 标签对象.offsetWidth - 标签对象.clientWidth - 标签对象.clientLeft;





        // 鼠标按下事件     mousedown
        let div = document.querySelector('div');
        div.onmousedown = function () {
            console.log(123);
        }
        // 鼠标抬起事件     mouseup
        div.onmouseup = function () {
            console.log(456);
        }

        // 鼠标进入事件     mouseover
        div.onmouseover = function () {
            console.log(123);
        }

        // 鼠标离开事件     mouseout
        div.onmouseout = function () {
            console.log(456);
        }


        // 获取元素位置:
        //标签对象.offsetLeft 获取元素的位置默认是参照页面左上角   
        //标签对象.offsetLeft 如果父元素有定位,就参照父元素
        let div = document.querySelector('.one');
        console.log(div.offsetLeft);


        // 延迟函数:
        // 只能调用一次
        // 第二个参数是多少毫秒后执行一次
        // 语法: setTimeout(函数名, 延迟时间(毫秒单位))
        function fn() {
            console.log(123);
        }
        setTimeout(fn, 2000);




        // 递归函数: 在函数内部函数自己调用自己
        // 递归函数: 就是一个死循环
        // 如果需要停止递归函数,则设置return关键字
        let i = 1;
        function fn() {
            i++;
            console.log(123);
            if (i >= 5) {
                return;
            }
            fn();
        }
        fn();



        // ☞ clearTimeout(id)可以用来停止延迟函数
        //延迟函数和定时器的另外一种写法:
        // setTimeout(函数名, 毫秒时间);
        // setInterval(函数名, 毫秒时间);
        // 或者
        // setTimeout(function(){逻辑代码}, 时间);
        // setInterval(function(){逻辑代码}, 时间);
    </script>
</body>













webAPI 第六天

<body>
    <script>
        // 动画的处理方式:
        // 1.自定义动画,然后通过类名添加
        // 2.使用第三方解决方案
        // 3.利用js封装:  定时器  或者 延迟函数+递归函数
        // js封装动画案例
        btn.onclick = function () {
            fn()
        }

        function fn() {
            if (starH >= endH) {
                return
            }
            starH += jia
            box.style.height = starH + 'px'
            setTimeout(fn, 5)
        }







        // 正则表达式
        // 验证
        两种验证与表达式的对比状态
        表达式.test(内容) : 返回布尔值, true 代表符合  false 不符合
        表达式.exec(内容) : 返回数组, 代表符合, 返回 null 不符合




        // 用于         表单验证  + 敏感词替换
        // 格式         let 正则对象 = //

        // 字符串中包含连续的abc即可
        let reg = /abc/;
        // 字符串必须只能是abc
        let reg = /^abc$/
        // 字符串为字母a 到 f中的一个即可
        let reg = /^[a-f]$/;

        // *  >= 0
        // +  >= 1
        // ?  0或者 1

        { n } 等于n次
        { n,} >= n 次
        { n, m } n 到 m 次
        let reg = /^[a-c]{5, 8}$/

        // g 检查所有
        // i 不分大小写
        let reg = /^a$/gi
        let str = 'abbbcccaddda'




        // 预定义类
        \d: 代表[0 - 9]
        \w: 代表[a - zA - Z0 -9_]

        \D: 非[0 - 9]之间的值
        \W: 非[a - zA - Z0 -9_] 之间值

        \s: \t\r\n
        \S: 非 特殊符号



        // 智能表单
        type = "number" 强制数字
        type = 'email'  强制邮箱
        type = 'tel'
        type = 'url'



        // 表单事件  
        input事件: 当用户输入内容的时候执行
        focus事件: 当输入框获取焦点的时候执行
        blur事件: 当输入框失去焦点的时候执行




        // 敏感词替换
        // replace(正则表达式(被替换的内容),替换用的字符)
        let reg = /敏感词/gi
        btn.onclick = function () {
            let texts = text.value
            div.innerHTML = texts.replace(reg, '***')
        }




        // 键盘事件
        // keydown : 键盘按下执行  
        html.onkeydown = function () {
            console.log(1111);
        }
        // keyup   : 键盘抬起执行
        html.onkeyup = function () {
            console.log(2222);
        }
        // keypress: 键盘按下执行 (shift 方向键  alt  ctrl ...)
        html.onkeypress = function () {
            console.log(3333);
        }





        // 如何获取键盘按键
        // 通过 事件对象参数 获取按键信息
        // 获取键内容
        事件对象参数.key
        // 获取键名称
        事件对象参数.code
        // 获取键号
        事件对象参数.keyCode

    </script>
</body>













webAPI 第七天

<body>
    <script>
        //js顶级对象: window
        //☞特点: window顶级对象可以省略不写
        //☞document是window对象中的一个属性
        //☞未加前缀的函数默认被添加到了window对象中
        function fn() { }
        window.fn()



        // window对象属性
        // ☞ navigator对象: 保存浏览器相关信息
        获取当前网络状态 true  false
        navigator.online
        // ☞ location对象: 保存了网页地址
        获取 / 设置网站地址: location.href | location.href = '地址'
        刷新页面: location.reload() | location.reload(true)
        // ☞ history对象: 保存了历史记录
        history.forward()   去下一个历史记录
        history.back()      去上一个历史记录
        history.go(1)       去往相对于当前页面第 1 个页面



        // window对象方法
        文字弹窗     alert()
        输入框弹窗   prompt()
        确认弹窗     confirm()
        延迟函数     setTimeout()
        定时器       setInterval()



        // windowd对象事件
        load事件: 当页面中的标签加载完成后触发事件
        resize事件: 当浏览器尺寸(视口尺寸)大小发生改变触发事件




        // 文件读取:流程
        // a) <input type="file">
        // b) 给按钮注册 change事件
        // c) 获取上传文件:  事件源.files[0]    
        // d) 读取文件. 创建一个读取文件的对象    let read = new  FileReader();
        // e) 读取文件 对象.readAsText(文件)    对象.readAsDataURL(图片)
        // f) 获取读取结果: read.onload事件中通过 read.result 获取读取的结果

        let input = document.querySelector('input')
        let h1 = document.querySelector('h1')

        input.onchange = function () {
            let file = input.files[0]
            let reader = new FileReader()
            reader.readAsText(file)
            reader.onload = function () {
                h1.innerHTML = this.result
            }
        }


        dragover    鼠标进入事件源, 未抬起按键时
        drop        鼠标松开时
        // 拖拽读取:流程
        // ☞ dragover事件给目标区域注册
        // ☞ drop事件给目标区域注册
        // ☞ 在事件中阻止浏览器默认行为:  事件对象参数.preventDefault()
        // ☞ 在drop事件中获取文件
        // a) 通过  事件对象参数.dataTransfer.files[0]  获取文件
        // b) 创建读取器对象   new  FileReader()
        // c) 通过对象调用  readAsText(文件) readAsDataURL(文件)
        // d) onload事件中通过 result 获取读取的结果
        let div = document.querySelector('div')
        div.ondragover = function (cc) {
            cc.preventDefault()
        }
        div.ondrop = function (cc) {
            let file = cc.dataTransfer.files[0]
            let reader = new FileReader()
            reader.readAsDataURL(file)
            reader.onload = function () {
                div.innerHTML = ''
                div.style.backgroundImage = `url(${reader.result})`
                // let img = document.createElement('img')
                // img.src = reader.result
                // div.appendChild(img)
            }
            cc.preventDefault()
        }



        // 阻止默认行为
        形参.preventDefault()




        // 本地存储
        // 保存数据 setItem 以键值对形式保存
        localStorage.setItem('key', 值);
        // 读取数据 getItem
        localStorage.getItem('key');
        // 删除数据 removeItem
        localStorage.removeItem('key');

        // localStorage数据
        // 持久化保存
        // 数据不会自动消失
        // 可以跨页面访问

        // sessionStorage
        // 页面关闭数据消失 
        // 只能在当前页面中访问


    </script>
</body>










JavaScript高级 第一天

<body>
    <script>
        //作用域: 代码起作用的区域
        //☞全局作用域: 函数外部都是全局作用域
        定义的变量(全局变量), 在任何的地方访问
        //☞局部作用域: 函数内部就是局部作用域
        在局部作用域中定义的变量(局部变量), 只能在当前作用域中使用
        function fn() {
            let a = 123;
            return a;
        }
        //☞块级作用域: {} let 或者 const关键字
        在块级作用域中定义的变量, 只能在当前作用域中使用
        if (true) {
            let a = 1
        }



        // 作用域链
        // 作用: 在程序中指导变量查找规则
        // 作用域链: 当程序在执行变量的时候,先在当前作用域中查找是否有变量,如果有则执行当前作用域中变量, 如果没有则沿着作用域链向上一级继续查找,找到为止
        // 在嵌套作用域中,多个作用域形成链状结构 ---> 作用域链





        // 函数提升 + 变量提升 
        // 函数提升:
        在程序中遇到函数的时候, 自动将函数的声明提升到当前作用域的开始位置, 不包含函数的调用
        // 函数提升案例
        fn();
        function fn() {
            console.log(123);
        }


        // 变量提升: 返回值为 undefined
        使用var关键字定义的变量, 那么会将变量的声明提升到当前作用域的开始位置, 不包含变量的赋值
        let 没有变量提升

        // 变量提升案例
        结果 ? 报错   原因: let 关键字定义的变量, 必须先定义后使用.let关键字定义的变量, 没有变量提升
        console.log(a);
        let a = 123;

        原因 ? undefined    原因: var 关键字声明的变量有变量提升
        console.log(b);
        var b = 123;





        // 闭包函数: 在函数fn中, 通过另外一个函数fn1使用了当前函数fn中的变量, 整体fn就叫闭包函数
        例: fn1中调用了a, 局部作用域中没有就向上寻找父级元素的a并调用, 此时整个fn都叫闭包函数
        function fn() {
            let a = 123;
            function fn1() {
                return console.log(a + 1);;
            }
            fn1();
        }
        fn();







        // 函数参数默认值
        为防止出现实参与形参数量不同而出现undefined, 给形参设置0的默认值
        function fn(a = 0, b = 0) {
            return a + b;
        }
        fn();





        // arguments    伪数组
        ☞ 在函数中用来保存实参信息的伪数组
        ☞ arguments.length 保存了实参的个数
        ☞ 通过循环遍历 arguments[索引] 得到具体实参的值
        ☞ 当形参个数不确定的时候, 使用arguments获取实参
        // 例:
        function cc() {
            for (let i = 0; i < arguments.length; i++) {
                console.log(arguments[i]);
            }
        }
        cc('aa', 'cc', 'pp')






        // 剩余参数:    ...参数名
        ☞ 在函数中通过  ...参数名
        ☞ 剩余参数最后是以数组形式存在的
        ☞ 剩余参数保存的也是实参的值
        ☞ 剩余参数必须写到形参的最后
        // 例:
        function fn(a, b, ...d) {
            // d 是剩余参数
            console.log(d);
        }
        fn(1, 2, 3, 4)






        // 箭头函数: 
        ☞ (形参1, 形参2) => { 函数体 }
        ☞ 按照自调用函数写法, 调用箭头函数((形参1, 形参2) => { 函数体 })();
        ☞ 将箭头函数赋值给一个变量, 通过  变量名() 调用;

        ☞ 如果只有一个形参, 则() 可以省略              形参1 => { 函数体 }
        ☞ 如果函数体中只有一行代码, 则 { } 可以省略.   (形参1, 形参2) => 函数体
        ☞ 如果函数体中只有一行代码且有返回值, 则 { } 和 return 可以省略    形参1 => 函数体
        ☞ 箭头函数中的this, 指向上级作用域中this的事件源
        // 例:
        let btn = document.querySelector('button')
        btn.onclick = function () {
            let anniu = () => {
                console.log(this);
            }
            anniu()
        }

        // 箭头函数和普通函数的区别
        用了箭头函数，this 就不是指向 window，而是父级（指向是可变的）
        不能够使用 arguments 对象
        不能用作构造函数，这就是说不能够使用 new 命令，否则会抛出一个错误
        不可以使用 yield 命令，因此箭头函数不能用作 Generator 函数



        // let const var
        const关键字: 定义常量的(1, 常量的值不能修改  2, 定义常量必须设置默认值, 3, cosnt会形参块级作用域)
        var关键字: 定义变量的(1. 变量可以先使用后定义  2, 变量提升   3 不会形成块级作用域)

    </script>
</body>












JavaScript高级 第二天

<body>
    <script>
        // 解构赋值: es6中通过解构赋值可以快速的获取数组或对象中的值方式
        // 本质: 获取数组 或者 对象中的值
        // 注意: 解构赋值只能在数组或对象中使用




        // 数组解构:
        // 数组解构赋值总结:
        a.只是从数组中取值的一种新方式而已
        b.动态将数组中的每一个值赋值给前面的变量
        c.如果变量的个数少于数组中值的个数, 程序不会报错, 会将数组中的值一一对应的赋值给变量
        d.如果变量的个数多余数组中值的个数, 那么多余的变量的值默认是undefined
        // let [变量1, 变量2] = 数组;
        // let [变量1, 变量2] -----> 定义了若干个变量,不是定义数组
        // = 数组     ----> 程序会自动遍历数组中的值,然后将数组中的每一个值动态的赋值给前面定义的变量
        let ary = [{ 'uname': 'zs' }, { 'uname': 'ls' }, { 'uname': 'ww' }, { 'uname': 'lad' }];
        // 解构赋值: 将数组ary中每一个值动态赋值给变量a1,a2,a3,a4
        let [a1, a2, a3, a4] = ary;
        // 输出数组中每一个值
        console.log(a1, a2, a3, a4);




        // 对象解构: 
        let { 属性: 变量1, 属性: 变量2 } = 对象;
        // 对象解构赋值总结:
        //1. 对象解构赋值中,属性后面的变量可以和属性的名称一样
        let { uname: uname, uage: uage, ulike: ulike } = obj;
        console.log(uname, uage, ulike);
        //2. 如果属性名和变量名一样,则变量名可以省略不写,只能写一个属性即可
        let { uname, uage, ulike } = obj;
        console.log(uname, uage, ulike);
        // 访问对象中不存在的属性,则得到的结果是undefined





        // 创建对象方法
        1.字面量方式创建对象
        2.new Object 声明一个对象
        3.内置构造函数创建对象
        4.自定义构造函数创建对象
        5.工厂方式创建对象



        // ☞ 通过字面量方式创建对象
        let obj = {};

        // ☞ 通过内置构造函数创建对象
        let obj1 = new Object();
        // 内置构造函数: 本质上就是一个函数,创建对象
        // 通过构造函数创建对象必须添加new关键字

        // ☞ 通过工厂方式创建对象
        function stu(name, gender, score) {
            let obj2 = {};  // 或者let obj2 = new  Object();
            obj.name = name
            obj.gender = gender
            obj.score = score
            return obj
        }
        let ls = stu('雷神', '男', 100)
        let gtx = stu('钢铁侠', '男', 110)
        console.log(ls, gtx);

        // ☞ 自定义构造函数创建对象
        function Student(name, age, gender) {
            // 构造函数中的this指向构造函数创建的实例对象
            this.name = name
            this.age = age
            this.gender = gender
        }
        let zs = new Student('张三', '18', '男')
        console.log(zs);







        // 创建函数
        第一种（函数声明）：
        function sum1(num1, num2) {
            return num1 + num2;
        }
        第二种（函数表达式）
        var sum2 = function (num1, num2) {
            return num1 + num2;
        }
        第三种（函数对象方式）
        var sum3 = new Function("num1", "num2", "return num1+num2");














        toFixed(位数)
        显示小数后几位



        // 成员: 
        // 属性 +方法的总称
        function Student(uname) {
            //属性
            this.uname = uname;
            //方法
            this.eat = function () {
                console.log(123);
            }
        }
        // ☞ 实例成员:  
        在构造函数内通过this关键字设置的属性或方法
        通过实例对象设置的属性或方法(原因: 构造函数中的this就是实例对象)
        实例成员只能通过实例对象访问
        let zs = new Student('张三');
        console.log(zs.uname);
        zs.eat()

        // ☞ 静态成员: 
        在构造函数外部, 通过 构造函数 本身设置的属性或方法
        静态成员只能通过构造函数访问
        Student.myage = 23;
        Student.myeat = function () { }







        // 内置对象
        // Math 内置对象
        Math.random();
        Math.floor()
        // 数组内置对象
        let ary = [];
        ary.push();
        ary.pop()
        ary.length
        console.log();




        // 数组方法和属性
        let ary = new Array();

        // 翻转
        ary.reverse();    // reverse() 方法: 翻转数组
        例:
        let num = [1, 2, 3, 4, 5]
        let newnum = num.reverse()
        console.log(newnum);

        // 数组拼接
        ary.join();       // join() 方法: 将数组中的值拼接为字符串, 返回一个字符串,()里写什么就用什么插入
        let num = [1, 2, 3, 4, 5]
        let string = num.join('/')
        console.log(string);



        // 拼接字符串 括号里写什么就是穿插什么
        ary.concat(ary1); // concat()方法: 将数组合并为一个, 返回合并后的数组
        let zimu = ['a', 'b']
        let num = [1, 2, 3, 4, 5]
        let newnum = zimu.concat(num)
        console.log(newnum);

        // 获取数组长度
        ary.length

        // 添加数组内容
        ary.push(值)      // push()方法: 向数组的末尾添加值
        ary.unshift(值)   // unshift()方法: 在数组的开始位置添加值
        ary.splice(索引, 0, 添加的值);//splice()方法: 在数组的任意位置添加值

        // 删除数组内容
        ary.pop()         // pop()方法: 从数组的末尾删除
        ary.shift();      //从数组开始位置删除
        ary.splice(索引, 删除的个数);//从任意位置删除






        indexOf()     //根据值获取索引
        //特点: 从数组的开始向结束位置查找
        ary.indexOf('字符', 开始查找的位置);
        // 特点: 从数组末尾向开始位置查找
        ary.lastIndexOf('字符', 开始查找的位置);




        // 通过foEach 获取数值和索引
        let num = ['1', '2', '3', '4', '5']
        num.forEach(function (items, index) {
            console.log(items); // 数值
            console.log(index); // 索引
        });

        // 必须掌握: filter 过滤器, 根据条件将数组中对应的结果过滤出来
        // 总结:
        // 1. filter能够实现forEach实现的效果(遍历数组)
        // 2. filter的重点是通过遍历要得到自己想要的结果  filter(function (item, index) { }) 过滤筛选数组, 返回一个新数组
        let ary = [1, 2, 3, 4, 5, 6, 7, 8];
        let res = ary.filter(function (item, index) {
            return item % 2 == 0;
        })
        console.log(res);




        // 映射, 返回的是一个数组
        // 在程序中用来处理数组中的每一个值
        // 返回值: 将数组中原来的值出处理后进行返回 (返回的个数与原来的个数是相同的)
        // 语法: map(function(item, index){})
        let ary = [1, 2, 3, 4];
        let res = ary.map(function (item, index) {
            return item % 2 == 0;
        })
        console.log(res);













        // 日期方法
        new Date().getDate()	以数值返回天（1 - 31）
        new Date().getDay()	以数值获取周名（0 - 6）
        new Date().getFullYear()	获取四位的年（yyyy）
        new Date().getHours()	获取小时（0 - 23）
        new Date().getMilliseconds()	获取毫秒（0 - 999）
        new Date().getMinutes()	获取分（0 - 59）
        new Date().getMonth()	获取月（0 - 11）
        new Date().getSeconds()	获取秒（0 - 59）
        new Date().getTime()	返回自 1970 年 1 月 1 日以来的毫秒数

    </script>
</body>








JavaScript高级 第三天

<body>
    <script>

        //数组方法
        //☞实例成员方法
        arr.sort() // 数组排序,用于以首字母排序数组
        arr.reverse()   //颠倒数组中元素的顺序

        arr.push();     //数组尾部添加内容,同时会有一个返回值,返回的是新数组的长度
        arr.unshift();  //数组头部添加内容
        arr.splice(索引, 操作的个数, 替换的内容)    //插入、删除或替换数组的元素。不写替换的内容按删除处理

        arr.pop();      //删除并返回数组的最后一个元素
        arr.shift();    //删除并返回数组的第一个元素
        arr.splice(索引, 删除的个数);

        arr.indexOf()   //从数组的开始向结束查找 (从左向右找)   本方法区分大小
        arr.lastIndexOf()   //从数组的结束向开始查找 (从后向前找)

        arr.toString()  //以逗号分割,将数组转化为字符串
        arr.join()      //将数组拼接字符串,括号中可以确定分割符,不写分隔符逗号拼接,写一个空引号就是无缝拼接
        arr.concat(arr2, arr3)    //合并两个或多个数组,会返回一个新数组

        arr.forEach(function (item, index) { });//遍历,获得内容和索引
        let 变量 = arr.filter(function (item, index) { return item }); //根据条件将数组中对应的结果过滤出来    返回值组成新的数组
        let 变量 = arr.map(function (item, index) { })     //映射,  将数组中原来的值出处理后进行返回 返回值组成新的数组



        arr.reduce() // 用于数组运算    第一个值为默认值,在括号最后的值为赋予sum的初始值,最后的 return 是返回sum的值,因此可以以此对数组进行运算
        return this.list.reduce((sum, items) => {
            if (items.goods_state) {
                sum += items.goods_count * items.goods_price;
            }
            return sum;
        }, 0);



        arr.every() 方法用于检测数组所有元素是否都符合指定条件
        // 1. 如果数组中检测到有一个元素不满足，则整个表达式返回 false ，且剩余的元素不会再进行检测。
        // 2. 如果所有元素都满足条件，则返回 true。 
        // !!!!!!!!         every() 不会对空数组进行检测。
        arr.some()  同every一样用来判断是否符合条件, 但是返回值是只要一个元素满足条件, 则返回 turn, 且剩余的元素不会再进行检测。





        arr.findIndex() 与every用法完全一样, 只是返回的值是符合条件的 数值 的 索引











        arr.slice(2, 4) //用于返回一个切割数组的新数组,第一个参数为开始切割的索引,第二个参数为结束索引参数(不包括此索引)



        arr.map(执行函数) // 对每个数组元素执行函数来创建新数组,
        // 给每一个数值进行操作后 return 替换掉原数值
        var numbers1 = [45, 4, 9, 16, 25];
        var numbers2 = numbers1.filter(myFunction);

        function myFunction(value, index) {
            return value * 2;
        }



        // 数组排序
        let points = [40, 100, 1, 5, 25, 10];
        points.sort(function (a, b) { return a - b });
        console.log(points);
        // 排序函数 比值函数
        // 若 a 小于 b，在排序后的数组中 a 应该出现在 b 之前，则返回一个小于 0 的值。
        // 若 a 等于 b，则返回 0。
        // 若 a 大于 b，则返回一个大于 0 的值。







        //☞ 静态方法(静态成员): 
        Array.from(伪数组)  //将伪数组转化为真数组
        Array.prototype.slice.call(伪数组)

        // for in 语法遍历自定义对象
        for (变量 in 对象) {
            在此执行代码
        }







        // 字符串方法

        // 转大小写
        toUpperCase()转大写
        toLowerCase()转小写
        let str = 'ABC';
        console.log(str.toUpperCase());
        console.log(str.toLowerCase());


        // 分割字符串
        split()

        // 提取字符串中两个指定的索引号之间的字符
        substring(开始索引, 结束索引)  //开始到结束
        substr(开始索引, 长度)         //开始 长度

        // 检测字符串是否以某个字母开始 结束
        endsWith()      检测是否以某个字母结束
        startsWith()    检测是否以某个字母开始

        replace('被替换的字符', '替换后的字符')   替换字符串内容

        padStart(位数, '值')    头部补全, 是否够几位数, 如果不够在前面添加对应的内容
        padEnd('位数', '值')    尾部补全, 是否够几位数, 如果不够在后面添加对应的内容




        // 字符串中的方法:
        // indexOf()方法: 

        // 获取字符串中每一个字符对应的索引号
        indexOf()获取字符对应的索引号, 如果找到了则返回对应的索引号
        indexOf()获取字符对应的索引号, 如果没有找到则返回 - 1
        // lastIndexOf()方法: 
        获取字符串中每一个字符对应的索引号
        lastIndexOf()方法 indexOf()方法 使用与数组中的方法一样
        let str = 'abca';
        console.log(str.indexOf('w'));
        console.log(str.lastIndexOf('a'));


        // split()分割字符串: 按照字符串中符号将字符串分割,不写符号就直接分割
        // split方法只能是字符串调用
        // 返回的结果是一个数组
        str.split('|')
        // 要求: 从字符串获取用户名zs , 密码123 ,年龄 23
        let str = 'uname=zs&&pwd=123&&age=23';
        let res = str.split('&&');
        let myname = res[0];
        console.log(myname.split('=')[1]);




        //============================ substring() ===============
        // substring(startIndex[,endindex])方法: 用来截取字符串
        第一个参数: 表示开始索引
        第二个参数: 表示结束索引     可以设置也可以不用设置
        // a) 如果不设置,代表直接截取到字符串的末尾
        // b) 如果设置了第二个参数,则代表截取到位置处,但是不包含结束位置处的字符
        // 返回截取后的结果: 返回字符串
        let str = 'abc中国abc';
        let res = str.substring(1, 2);
        let res1 = str.substring(3, 5);
        console.log(res);


        //=============================== substr()===================
        // substr(startIndex,截取数量) 方法: 用来截取字符串
        substr(索引, 截取数量)
        第一个参数: 表示开始索引
        第二个参数: 表示截取数量
        // a) 第二个参数不设置,代表截取到字符串末尾
        let str = 'abcdef';
        // 从索引为1的位置起开始截取
        let res = str.substr(1, 2);
        console.log(res);



    </script>
</body>







JavaScript高级 第四天

<body>
    <script>
        // call方法: 调用函数(构造函数)
        // 语法: 函数名.call()
        function fn() {
            console.log(123);
        }
        fn();
        // 通过call方法调用fn函数
        fn.call();
        1. 通过call调用函数(普通函数 + 构造函数)
        2. 调用函数的时候, 修改函数中的this指向
        3. 调用带有参数的函数, 函数.call(具体的对象, 实参1, 实参2);




        // 属性继承
        // 继承: 利用到call方法 
        // a) call调用函数
        // 函数名.call()
        // b) call修改函数中的this指向
        // 函数名.call(对象, 其他参数)


        // 继承: 在js中的继承,同样可以减少代码量
        // a) 属性继承
        // b) 方法继承


        // 属性继承演示:
        // 调用Father构造函数的时候,需要将Faher中的this修改为当前Son中的this指向
        // 一定要写this关键字, this指向的是实例对象
        function Father(uname, uage, ugender) {
            //this: 指向Father创建的实例对象
            this.uname = uname;
            this.uage = uage;
            this.ugender = ugender;
        }
        let zs = new Father('大张三', 35, '男');

        function Son(uname, uage, ugender, score) {
            // Father.call(this, uname, uage, ugender);
            let res = Father.bind(this, uname, uage, ugender);
            res();
            // 除了继承额外有需要添加的对象,另外写,不需要在继承中声明
            this.score = score;
        }
        let xzs = new Son('小张三', 10, '女', 100);

        // 方法继承(原型继承)
        Son.prototype = new Fater();





        // 类:es6中提出一个概念
        // 类的本质就是一个构造函数
        // 类的作用: 创建对象


        // 类使用方式:
        // a) 定义类 : class 自定义类名 {}
        // b) 通过类创建对象:  new 类名();
        // c) 通过类创建的对象叫 实例对象

        // 代码演示:
        // 定义学生类
        class Student {
            constructor() {
                属性内容
            }
        };
        // 通过类创建对象
        let zs = new Student();
        console.log(zs);



        // 通过类设置属性和方法
        // 设置属性
        // 语法: 通过 constructor函数设置属性

        // 设置方法:
        // 必须和constructor是并列关系,方法单独设置,相当于一个原型函数
        class Student {
            // 属性
            constructor(uname, uage, ugender) {
                this.uname = uname;
                this.uage = uage;
                this.ugender = ugender;
            }
            // 方法
            eat() {
                console.log('吃饭...');
            }
            // 方法
            sing() {
                console.log('唱歌');
            }
        }
        // 创建zs实例对象
        let zs = new Student('张三', 23, '男');
        // zs.eat();
        // zs.sing();
        console.log(zs);


        // 总结:
        // 1. 在类中通过 constructor设置属性
        // 2. 在类中设置方法,必须写到 constructor外部
        // 3. 在类中的方法,直接写方法即可,不能加function关键字





        //构造函数实现属性继承:
        //a) 在子构造函数中通过: 
        父构造函数.call(this, 参数);
        //b) 子构造函数要继承父构造函数中的方法:    
        子构造函数.prototype = new 父构造函数
        // 通过类实现继承:
        子类 extends 父类 { }

        // 代码演示:
        class F {
            constructor(uname, uage, ugender) {
                this.uname = uname;
                this.uage = uage;
                this.ugender = ugender;
            }
            eat() {
                console.log('123');
            }
        }
        // 继承
        class S extends F { }
        let zs = new S('张三', 23, '男');
        zs.eat();
        console.log(zs);



        //类总结
        // 1. 类中的this也指向创建的实例对象
        // 2. 类中的属性和方法之间相互访问的时候,必须加this关键字
        // 3. 类实现继承,通过 类名 extends 类名 {}
        // 4. 类继承的过程中,如果子类没有设置自己的构造函数,则直接使用
        // 5. 类继承的时候,如果子类中有自己的构造函数, 必须在构造函数中this前面加 super()
        // 6. super 调用父类中的构造函数








        // 数组去重
        let arr = [1, 2, 2, 6, 8, 4, 1, 2, 8, 6, 4]
        let arr2 = []
        arr.filter((items, index) => {
            if (!arr2.includes(items)) {
                arr2.push(items)
            }
        })
        console.log(arr2);
    </script>
</body>








JQuery 第一天

<body>
    <script>
        // JQuery
        JQ: 就是一个js库
        本质上: jQ就是一段js代码, jQ将webAPI中操作网页的各种方式进行了封装, 将封装后的js文件称为js库(jQ)
        jQ作用: 减少更少的代码量



        // jQ基本使用:
        ☞ 先下载JQ文件(文件带有 min.js----压缩版本       文件没有 min.js----开发版)
        ☞ 在网页中引入jQ文件, 本质上就是引入js文件(使用该文件中提供的各种方法, 才能使用JQ的写法)
        建议: 推荐将JQ文件在html结构后面引入


        // $符号
        $jQuery的别名
        $jQuery中的顶级对象




        // 入口函数
        // 当js代码写在html之前时,就可以用入口函数使js代码加载在html之后
        // 类似于原生js中的load事件功能
        $(function () { })
        $(document).ready(function () { })





        // $是jQ中的顶级对象
        // $符号表示jQuery的别名(能用$的,都可以使用jQuery)
        // ☞ 在原生js中,window是js中的顶级对象
        // ☞ 在jQ中, $是jQ的顶级对象
        let li = $('li')
        let li = jQuery('li')
            (jQuery === $)  //true





        // jQ对象特点:
        // a) jQ对象带有: jQuery.fn.init
        // b) jQ对象是一个数组
        let div = $('div');
        console.log(div);


        // 通过原生js得到的标签只能按照原生js提供的方式处理, 通过jQ得到的标签只能使用jQ提供的方法去处理, 二者不能通用
        // 如果原生js要用jQ中的方法,或者jQ要使用原生js中的方法,那么需要将DOM对象和jQ对象进行转换






        // DOM对象和JQ对象相互转换

        // 将DOM对象转化为jQ对象
        语法: $(DOM对象)
        let div = document.querySelector('div');
        // 将DOM对象转化为jQ对象    $(div1)
        console.log($(div));






        // 将jQ对象转化为DOM对象
        // div是一个jQ对象,jQ对象就是一个数组
        // jQ数组对象中保存的就是每一个DOM对象
        // 语法: jQ对象[索引]       div[0]
        let div = $('div');
        console.log(div[0]);





        // 通过jQ获取页面中的元素
        // 通用语法: $('css选择器');
        // a)标签选择器
        console.log($('li'));
        // b)类选择器
        console.log($('.one'))
        // c)id选择器
        console.log($('#two'));
        // d)复合选择器 (后代选择器  结构伪类选择器 ...)
        console.log($('ul li'));
        // e)结构伪类选择器
        console.log($('ul li:nth-child(2)'));



        //通过jQ提供的选择器获取元素

        // 通过索引获取元素
        $('li:eq(3)')   // 选中自由选择索引  :eq(索引)
        $('li:odd')     // 选中索引为奇数    :odd
        $('li:even')    // 选中索引为偶数    :even
        $('li:first')   // 选中第一个        :first
        $('li:last')    // 选中最后一个      :last


        // 获取父元素
        jQ对象.parent()         // 获取直接父元素   parent()      
        jQ对象.parents()        // 获取所有父元素   parents()
        jQ对象.parents('body')  // 获取选定父元素   li.parents('body')


        // 获取子元素   children(选择器)
        p.children()    // 返回直接子元素
        p.find('span')  // 获取所有符合条件子元素   find(选择器)


        // 获取兄弟元素     siblings(选择器)
        p.siblings()    // 获取所有兄弟元素
        p.siblings('h3')// 获取指定兄弟元素



        // 标签对象.nextAll(选择器) 
        h1.nextAll()
        获取当前标签的后面所有的兄弟元素(带有选择器: 代表获取指定的兄弟元素)

        // 标签对象.prevAll(选择器) 
        h1.prevAll('a')
        获取当前标签前面所有的兄弟元素(带有选择器: 代表获取指定的兄弟元素)







        // jQ注册事件
        // jQ中注册事件的时候,不需要手动遍历,因为jQ自己内部遍历元素(隐式迭代)
        // 语法: jQ对象.事件类型(function () { })
        // this是DOM对象,如果要使用jQ中提供的方式,则this必须用${} 括起来 $(this),以此来使用jQ的方法
        li.click(function () {
            $(this).css('background', 'cyan')
        })







        // 链式编程(jQ排他思想也用的到)
        // 操作事件样式时并且同时清空兄弟元素的样式
        // $(this).css('color', 'red').siblings().css('color', '#000');

        // 同一个元素操作两次css样式
        btns.click(function () {
            $(this).css('color', 'red').siblings().css('color', '#000');
        })

        // 同一个事件源注册两个事件
        last_li.mouseover(function () {
            let u2 = $(this).find('.u2');
            u2.css('display', 'block');
        }).mouseout(function () {
            let u2 = $(this).find('.u2');
            u2.css('display', 'none');
        })








        // jQ操作样式
        // jQ行内样式
        设置单个属性: jQ对象.css('css属性', 值);
        设置多个属性: jQ对象.css({ 'css属性': 值, 'css属性': 值 })


        // 类样式
        // jQ添加类名 
        div.addClass('bd');     //jQ对象.addClass('类名')  添加类名  
        1. 给标签添加类名, 如果要添加多个类名, 则需要使用空格隔开
        2. 添加类名的时候, 不会覆盖原来的类名

        // jQ移除类名
        div.removeClass('bd');  //jQ对象.removeClass('类名') 移除类名
        1. 移除类名设置指定要被移除的类名即可, 如果要移除多个类名, 则使用空格隔开
        2. 如果没有设置类名, 则表示清空所有类名

        // jQ切换类名
        div.toggleClass('bd');  //jQ对象.toggleClass('类名')  切换类名
        1. 切换类名
        2. 如果标签有该类名, 则会移除类名
        3. 如果标签没有类名, 则会添加类名




        // hover事件: 替代鼠标进入和鼠标离开事件
        // 语法: jQ对象.hover(function () { }, function () { })
        // 鼠标进入设置背景颜色,鼠标离开移除背景色
        let div = $('div');
        div.hover(function () { // 鼠标进入功能
            $(this).css('background', 'red');
        }, function () {        // 鼠标离开功能
            $(this).css('background', '');
        })
    </script>
</body>









JQuery 第二天

<body>
    <script src="./jQuery.min.js"></script>
    <script>
        // 通过jQ获取索引
        jQ对象.index()




        //webAPI解决网页中动画
        //1, 通过定时器实现  
        //2, 通过自定义css动画,调用类名
        //3, 通过调用第三方动画实现




        //jQ中提供的动画
        //内置动画 : 本质上就是控制元素的隐藏和显示
        //show() ---> 显示元素
        //show方法中有3个参数,如果不设置则没有动画效果
        第一个参数: 表示速度('slow', 'normal', 'fast')字符串 或者 设置一个毫秒数
        第二个参数: 表示切换效果, 默认值 'swing' 或者 匀速'linear'
        第三个参数: 回调函数, 动画完成后执行一次该回调函数
        // hide() ---> 隐藏元素
        // hide方法中的参数使用方式与show()中的参数使用一样
        // 代码演示内置动画
        btn1.click(function () {
            div.show('fast', 'linear', function () {
                // 可以写动画执行完执行的代码
                // 没有可以不写
            })
        })
        btn2.click(function () {
            div.hide('fast', 'linear')
        })

        // jQ内置动画
        // 显示元素/隐藏元素
        jQuery对象.show(): 显示元素
        jQuery对象.hide(): 隐藏元素

        // 以滑动方式显示元素/隐藏元素
        jQuery对象.slideDown(): 作用是用来显示元素
        jQuery对象.slideUp(): 作用是用来隐藏元素

        // 通过修改元素透明度实现显示元素/隐藏元素
        jQuery对象.fadeIn(): 作用显示元素(淡入效果)
        jQuery对象.fadeOut(): 作用隐藏元素(淡出效果)





        // 设置元素透明度
        jQuery对象.fadeTo(速度, 透明度, 切换效果, fn)
        // 例:
        btn.click(function () {
            div.fadeTo(1000, 0, 'linear', function () {
            })
        })




        // 打断动画队列stop()
        // 动画会默认排队执行,前一个动画未执行完不会被打断,多数情况下需要打断
        // 通过stop()方法将动画队列停止掉,必须在动画前面调用stop()方法
        // 例:
        btn1.click(function () {
            div.stop().slideDown(3000, 'linear', function () {
            })
        })
        btn2.click(function () {
            div.stop().slideUp(3000, 'linear', function () {
            })
        })







        // jQuery设置自定义动画
        jQuery对象.animate(属性, 速度, 切换效果, 回调函数)
        // 例:
        div.click(function () {
            $(this).animate({
                'width': '400px'
            }, 2000, 'linear', function () {
                console.log(123);
            });
        })
        // 注意事项:
        // 1. 第一个参数必须以对象的方式设置
        // 2. 自定义动画中的属性不是所有的属性都支持
        // 3. 与颜色相关的属性,与2d转化或3d转化相关的属性不支持

        //如果非得使用animate设置不支持的属性
        //☞ 自己写动画效果,然后通过类名添加实现 (webAPI)
        //☞ 网上找支持的插件(jQ),必须放到jQ文件的后面





        // JQ中获取非表单元素中的内容
        jQ对象.text()
        jQ对象.html()
        // jQ中给非表单元素设置内容
        jQ对象.text(值)
        jQ对象.html(值)
        // 与innerText和innerHTML赋值效果是一样






        // 通过jQ获取表单元素中的内容
        jQ对象.val()
        // 通过jQ设置表单内容
        jQ对象.val(值)





        // jQ遍历数据的方法
        jQ对象.each(function (index, item) { })
        $.each(被遍历的数组(jQ对象数组或者定义的数组), function (index, item) { })





        // 获得标准属性
        jQ对象.prop(属性, 属性的值)

        //  获取自定义属性
        jQ对象.attr(属性, 属性的值)

    </script>
</body>






JQuery 第三天

<body>
    <script src="./jQuery.min.js"></script>
    <script>
        // JQ删除标签
        jQ对象.remove() 将当前标签删除
        jQ对象.empty()  将当前标签中的内容全部删除(不删标签)


        // 创建元素
        let res = $('<h1></h1>')
        res.text('哈哈哈哈哈')


        // 添加元素
        添加到末尾    append  $(父元素).append(创建的元素)
        添加到开始    prepend $(父元素).prepend(创建的元素);



        // jQ获取元素大小
        jQ对象.width()----> 获取当前元素内容区域的宽度
        jQ对象.innerWidth()----> 获取当前元素内容区域 + 内边距
        jQ对象.outerWidth()----> 获取当前元素的实际大小(内容 + 内边距 + 外边框)






        // jQ中获取元素位置
        jQ对象.offset()     以整个页面为准获取元素位置
        jQ对象.position()   遵循子绝父相, 若父元素有定位则以父元素为准获取元素位置





        // jQ中获取滚动的距离(位置)
        JQ对象.scrollTop()
        // 例: 需要在滚动事件中获取
        $(window).scroll(function () {
            console.log(123);
            console.log($(this).scrollTop());
        })





        // jQ注册事件:
        jQ对象.事件类型(function () { })
        jQ对象.on('事件类型', function () { })
        // 使用on的方式一次可以给标签注册多种不同的事件类型




        // jQ委托事件
        $('父元素').on('事件类型', '简单选择器', function () { })
        // 例:
        $('ul').on('click', 'li', function () {
            console.log($(this).text());
        })



        // jQ移除事件
        // 非委托方式
        jQ对象.off('事件类型')
        // 委托方式
        父元素.off('事件类型')
        // 移除委托事件中指定的事件
        父元素.off('事件类型', '选择器')




        // 表单
        // 提交数据
        action属性: 设置表单提交地址
        method属性: 设置表单提交方式  get(默认方式)  post
        // get提交数据:
        数据在地址栏中可见
        get重点在于从服务端获取数据
        // post提交数据: 
        数据是通过后台异步提交(地址栏看不到数据)
        post重点在于提交数据(注册信息)
    </script>
</body>




ES6

<body>
    <script>
        // ES6新增语法
        1、新增声明命令 let 和 const
        2、模板字符串``
        3、函数的扩展
        4、对象的扩展
        5、for...of 循环
        6、/import 和 export/
        7、Promise 对象
        8、解构赋值
        9、Set 数据结构
        10、class/




        // var 、let、const 之间的区别（必会）
        区别
        var 声明变量可以重复声明，而 let 不可以重复声明
        var 是不受限于块级的，而 let 是受限于块级
        var 会与 window 相映射（会挂一个属性），而 let 不与 window 相映射
        var 可以在声明的上面访问变量，而 let 有暂存死区，在声明的上面访问变量会报错
        const 声明之后必须赋值，否则会报错
        const 定义不可变的量，改变了就会报错
        const 和 let 一样不会与 window 相映射、支持块级作用域、在声明的上面访问变量会报错



        ES6 对 String 字符串类型做的常用升级优化
        优化部分    ES6 新增了模板字符串，`` 可以代替加号拼接字符串, 让代码简洁干净
        升级部分:
        includes()  判断字符串中有无查找的内容, 返回的是布尔类型, 有true, 无false   取代indexOf()
        startsWith() 方法用于检测字符串是否以指定的子字符串开始
        endsWith() 方法用于测试字符串是否以指定的后缀结束
        padStart(最小长度, 补全的字符串) 头部补全
        padEnd(最小长度, 补全的字符串)   尾部补全
        repeat()    '字符串'.repeat(3); 复制三次    结果为  '字符串字符串字符串'



        ES6 对 Array 数组类型做的常用升级优化
        解构赋值    let [a, b, c] = [5, 6, 7]
        扩展运算符  ...


    </script>
</body>











数据可视化 01

<body>
    <!-- 1. 网页中显示统计图步骤 -->
    ☞ 引入对应的js文件
    ☞ 准备一个用来显示统计图盒子
    ☞ 初始化显示统计图
    a) 获取对应的盒子
    let myChart = echarts.init(document.getElementById('left_pie'));

    <!-- b) 设置配置选项 -->
    let option = {
    属性: 值
    }

    <!-- c) 调用配置 -->
    myChart.setOption(option);


    <!-- 饼状统计图配置属性总结: -->

    1. radius: [10, 60] 属性表示设置图表半径大小(调整大小)
    2. center: ['50%', '50%'], 设置显示位置
    3. itemStyle: { // 设置边框圆角borderRadius: 5 } 每一条数据对应的样式
    4. color: 设置显示颜色
    5. labelLine: 设置视觉引导线



    <!-- 地图配置属性总结 -->

    1. 在js文件将地图中的所有代码全部拷贝

    2. a) 获取对应的盒子
    let myChart = echarts.init(document.getElementById('left_pie'));

    3. myChart.setOption(option); 调用配置选项

    (如果地图没有显示: 自调用函数必须以封号结束, 自调用函数也需要调用)

    4. 在 option 中修改配置属性
    ☞ backgroundColor: 'rgba(255,255,255, 0.1)' 设置背景颜色
    ☞ 在 geo 配置中修改
    a) zoom: 1.2, 设置默认缩放比
    b) itemStyle: 中设置相关的样式颜色



    <!-- ☞ 柱状图配置 -->
    1) grid 属性 ---> 设置柱状图大小
    2) grid 中 通过 show ----> 显示网格
    3) grid 中 通过 borderColor: '#00596d' ---> 设置边框颜色
    4) X轴
    axisTick ----> 隐藏刻度线
    axisLabel ----> 设置刻度线对应的文字颜色
    5) Y轴
    splitLine ----> 设置数据分割线样式
    axisTick ----> 设置y轴刻度线
    axisLabel -----> 设置Y轴刻度线文字颜色

    <!-- 6) data数据中 ----> itemStyle 单独设置每一条数据样式 -->

    <!-- 7) 线性渐变效果 -->
    itemStyle: {
    color: {
    type: 'linear',
    x: 0,
    y: 0,
    x2: 0,
    y2: 1,
    colorStops: [{
    offset: 0, color: 'red' // 0% 处的颜色
    }, {
    offset: 1, color: 'blue' // 100% 处的颜色
    }],
    global: false // 缺省为 false
    }
    },
    }






    <!-- ☞ 折线图基本配置总结 -->

    a) grid: {
    // 设置大小
    left: '0%',
    top: '20%',
    right: '0%',
    bottom: '0%',
    // 设置文字溢出正常显示
    containLabel: true,
    // 显示网格
    show: true,
    // 设置边框颜色
    borderColor: '#01233e'
    },

    <!-- b) 分割线颜色 -->
    splitLine: {
    lineStyle: {
    color: ['#438be5']
    }
    },
    <!-- c) 设置坐标轴颜色 -->
    axisLine: {
    lineStyle: {
    color: '#438be5'
    }
    }

    <!-- d) 图例样式 -->
    legend: {
    <!-- // 设置图例前面样式 -->
    // itemStyle: {
    // color: 'red'
    // }
    <!-- // 设置图例文字颜色 -->
    textStyle: {
    color: '#4996f5'
    }
    },
</body>





数据可视化 补充

<body>
    <!-- 判断数字类型 -->
    1.正则表达式/\d/
    2.判断非数字
    isNaN() 返回的是一个布尔类型结果






    <script>
        // 本地存储: 简单版的数据库(保存数据)

        // 区别:
        localStorage: 属于持久化保存
        sessionStorage: 属于临时保存

        // 相同点:
        1. 保存数据 和 获取数据 都是通过键值对方式操作的
        localStorage.setItem('abc', 123);
        console.log(localStorage.getItem('abc'));


        // 2. 保存对象格式的数据, 需要将对象进行转换, JSON.stringify()  JSON格式的字符串
        let obj = {
            uname: 'zs'
        }
        localStorage.setItem('people', JSON.stringify(obj));

        // 3. 获取数据后,一般都要将得到的JSON格式的字符串转换为对应的对象, 通过JSON.parse() 进行转换
        console.log(JSON.parse(localStorage.getItem('people')).uname);








        // 移动端事件介绍
        // touch事件: 触碰
        // 1)touchstart事件: 类似于鼠标按下事件 (手指按下的时候触发)
        // 2)touchend事件:   类似于鼠标抬起事件 (手指离开触发)
        // 3)touchmove事件:  类似于鼠标移动事件 (手指按下并移动的时候触发)

        //  代码演示:
        let div = document.querySelector('div');

        // 推荐使用addEventListener注册事件
        div.addEventListener('touchstart', function () {
            console.log('touchstart');
        });

        div.addEventListener('touchend', function () {
            console.log('touchend');
        })

        div.addEventListener('touchmove', function () {
            console.log('touchmove');
        })








        // 移动端事件也有事件对象参数
        // 事件对象参数: 获取与手指相关的信息

        let div = document.querySelector('div');

        div.addEventListener('touchstart', function (e) {
            console.log(e);

            // 事件对象参数.touches
            // a) 获取位于手机屏幕上的手指信息
            // b) 返回的结果是一个数组, 数组的长度代表手指的个数
            // c) 数组中的每一个具体值,代表的就是一个手指对象
            // d) 通过 clientX/ clientY 或者 pageX / pageY 获取手指位置信息


            // 事件对象参数.targetTouches
            // a) 获取位于手机屏幕中元素身上手指信息
            // b) 返回的结果是一个数组,数组的长度代表元素身上手指的个数
            // c) 数组中的每一个具体值,代表的就是一个手指对象
            // d) 通过 clientX/ clientY 或者 pageX / pageY 获取手指位置信息
        })
    </script>
</body>









ajax 第一天

<body>
    <script>
        内容.trim();    // 去除空格
        内容.focus();   // 获取输入框光标   输入框聚焦




        // get 获取元素，绑定事件
        // 4个参数: 路径，传递给服务器的参数，成功的回调函数，希望返回的数据类型
        let url = 'http://www.liulongbin.top:3006/api/getbooks';
        // res参数代表从服务器获取的数据
        $.get(url, { id: 5, bookname: "西游记" }, function (res) {
            console.log(res);
        });


        // post 定义路径和参数
        let url = 'http://www.liulongbin.top:3006/api/addbook';
        let obj = {
            bookname: '三体之地球往',
            author: '刘慈欣',
            publisher: '中央人民出版社'
        };
        // 发送post类型的ajax
        $.post(url, obj, function (res) {
            console.log(res);
        });


        // ajax的方式获取数据
        $.ajax({
            method: 'GET',
            url: 'http://www.liulongbin.top:3006/api/getbooks',
            data: {
                id: 1
            },
            success: function (res) {
                console.log(res);
            }
        })


        // ajax的方式上传数据
        $.ajax({
            method: 'POST',
            url: 'http://www.liulongbin.top:3006/api/addbook',
            data: {
                bookname: '三体之死神永生',
                author: '刘慈欣',
                publisher: '中央人民出版社'
            },
            success: function (res) {
                console.log(res);
            }
        });
    </script>
</body>







ajax 第二天

<body>
    <script src="./lib/jquery.js"></script>
    <script>
        // form表单收集数据
        需要表单中的 < input > 中声明了value和name才可以获取


        submit // 表单的提交事件
        e.preventDefault(); // 阻止表单默认提交

        // 例:
        获取的表单数据需要加 name 和 value('获取的内容')
        $("form").on('submit', function (e) {
            e.preventDefault();
            // 两种快速获取表单参数的方式:
            console.log($("form").serialize());     // 字符串方式存储
            console.log($(this).serializeArray());  // 数组方式存储
        })


        // 表单中 有四种数据要注意
        1. disabled 无法获取， readonly 可以获取；
        2. file 无法获取文件域的值, 将来文件上传需要单独操作
        3. type = "hidden" 就是隐藏域，可以获取到他的值
        4. button的type属性，值如果为button，无法触动submit事件, 默认type为submit可以获取




        // 编码
        alert(encodeURIComponent('紫川'));
        // 解码
        alert(decodeURIComponent('%E7%B4%AB%E5%B7%9D'));



        // $.ajaxPrefilter() 能够拦截 $.get() $.post() $.ajax(); 而且是发送和接收都会拦截;
        $.ajaxPrefilter('公共地址') //设置在 jQruey 和 js 代码之间新建一个script
        $.ajaxPrefilter(function (option) {
            option.url = 'http://www.liulongbin.top:3006' + option.url;
        });



        // 原生get XMLHttpRequest
        // 1.创建 xhr 实例
        let xhr = new XMLHttpRequest();
        // 2.设置请求方式和资源路径     路径和资源写在一起,中间用?隔开
        xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1&bookname=西游记');
        // 3.发送请求
        xhr.send();
        // 4.接收
        xhr.onreadystatechange = function () {
            // 输出响应信息
            console.log(xhr.response);
        }


        // 原生post XMLHttpRequest
        // 1.创建 xhr 对象
        let xhr = new XMLHttpRequest();
        // 2.设置请求方式和资源路径
        xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
        // 注意1: 设置请求头 - 告诉后端发送的参数类型是什么样的;
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        // 注意2: post请求体，参数要写道send()里面;
        xhr.send('bookname=雍正王朝&author=二月河&publisher=河北人民出版社');
        // 接受响应数据 - 绑定位置，不影响接收数据的触发
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
                // JSON.parse()可以把JSON类型的字符串转换为对象类型
                let obj = JSON.parse(xhr.response);
                console.log(obj);
            }
        }

        // xhr对象.readyState
        代表四个阶段
        new 创建完, 返回的是 0
        open 设置完请求方式和资源路径, 返回 1
        send 是请求, 但是此时没有接收到, 所以返回的还是 1
        在 xhr.onreadystatechange 中是已经接收成功, 所以 2 3 4 都在这显示
        2 表示send一定调用了，并且已经接收到响应头
        3 示正在接收服务器返回的数据（可能已接收完毕，也可能正在接收中，取决于数据量的大小）
        4 数据接收完成

        // xhr对象.status
        响应分为五类：
        信息响应(100–199) ，
        成功响应(200–299) ，
        重定向(300–399) ，
        客户端错误(400–499)
        服务器错误(500–599) 。
        常用状态码
        200 OK - 请求成功
        400 Bad Request - 1、语义有误，当前请求无法被服务器理解。2、请求参数有误。
        401 Unauthorized - 当前请求需要用户验证。
        404 Not Found - 请求失败，请求所希望得到的资源未被在服务器上发现。
        500 Internal Server Error - 服务器遇到了不知道如何处理的情况。
    </script>



    <!-- 封装原生ajax -->
    <script>
        function myAjax(ajax) {
            // 创建原生ajax
            let xhr = new XMLHttpRequest()

            // 判断条件输出
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    let obj = JSON.parse(xhr.response)
                    ajax.success(obj)
                }
            }



            // 转化data     数据形式 {a:1,b:2,c:3}   变成  a=1&b=2&c=3
            function ajaxdata(data) {
                let arr = []
                for (var n in data) {
                    // 遍历后变为  [ a=1,b=2,c=3 ]
                    arr.push(`${n} = ${data[n]}`)
                }
                // 将数组拼接用&   a=1&b=2&c=3
                console.log(arr.join('&'));
                return arr.join('&')
            }
            let qs = ajaxdata(ajax.data)




            // 判断类型,设置地址和data
            if (ajax.method.toUpperCase() == 'GET') {
                xhr.open('GET', ajax.url + '?' + qs)
                xhr.send()
            } else if (ajax.method.toUpperCase() == 'POST') {
                xhr.open('POST', ajax.url)
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
                xhr.send(qs)

            }
        }
    </script>
</body>







ajax 第三天

<body>
    <script></script>
    <script src="./lib/axios.min.js"></script>
    <script src="./lib/jquery.js"></script>
    <script>
        // ajax事件
        1.xhr.timeout = 函数    //  超时触发
        2.xhr.onload = 函数     //  请求成功触发
        3.xhr.onerror = 函数    //  请求失败时触发
        4.xhr.upload.onloadstart    //开始上传时触发
        5.xhr.upload.onloadend  //  上传结束时触发
        6.xhr.upload.onprogress //  上传数据时,周期性触发



        // ajax超时处理 timeout
        // level2新特性，在open之前设定！
        let xhr = new XMLHttpRequest(); // 创建
        xhr.timeout = 1000;     //  设定超时限定时间
        xhr.ontimeout = function () {   // 处理超时设置
            alert('请求超时，请检查网络，重新发送请求！');
        }
        xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
                console.log(xhr.response);
            }
        }


        // ajax请求成功触发 load
        let xhr = new XMLHttpRequest(); // 创建
        xhr.open('POST', 'http://www.liulongbin.top:3006/api/getbooks');
        xhr.send();
        xhr.onload = function () {// 新增事件，替代原有的 onreadystatechange  xhr.readyState==4 && xhr.statue == 200 省略了
            console.log(xhr.response);
        }
        xhr.onerror = function () {// 请求错误的时候触发 - 网络不通畅，会触发 onerror  （了解）
            alert('请求出现错误，请检查网络！');
        }





        // 表单对象操作
        let form = document.querySelector('form')
        form.onsubmit = function (e) {
            e.preventDefault()  // 阻止表单跳转
            // let fd = new FormData(form)
            // ...可以拆解
            // console.log(...fd);


            let fd2 = new FormData();
            // 添加，修改，获取
            fd2.append('email', 'lvchao@itcast.cn'); // 只需要掌握 append();
            fd2.set('address', '三里屯');
            console.log(fd2.get('address'));
            // 利用扩展运算符，拆解后输出
            console.log(...fd2);
        }



        // 上传文件
        // FormData不需要设置请求头
        需要    JSON.parse(xhr.response)




        // jQuery
        // 在jQuery需要将contentType processData 设置为 false
        // 区分大小写，false不能带引号，不需要设置 Content-Type: 默认值了；
        contentType 编码
        contentType: false
        // 区分大小写，false不能带引号，参数不需要编码！
        processData 为 ture, 则data里的数组内容不会自动生成字符串传到后台
        processData: false




        // h5新增的进度条标签
        // <progress max = "200" value = "0"></progress>
        形参.total     // 文件总大小
        形参.loaded    // 已经上传的数据大小

        上传文件jQuery需要自己定义方法
        xhr: function () {
            // 获取xhr
            // let xhr = new XMLHttpRequest(); // 创建新xhr
            let xhr = $.ajaxSettings.xhr(); // 获取内置的xhr
            // 回归到原生js
            xhr.upload.onprogress = function (e) {
                $('progress').attr('max', e.total);
                $('progress').attr('value', e.loaded);
            }
            // 进度条能做，显示隐藏留作业！
            // 注意!!!!!!!!!!!
            return xhr;
        }





        // 同步异步
        1.js代码开始执行后，主线程执行栈中会把任务分为两类
        2.一类是同步任务, 一类是异步任务; 主线程执行栈优先执行同步任务，
        3.异步任务会被放入特定的处理程序中，满足条件后，被放到消息(任务 / 事件)队列中，
        4.主线程执行栈中所有的同步任务执行完毕之后，通过事件循环去消息(任务 / 事件)队列中，
        5.挑选优先满足条件的程序，放入主线程执行栈中执行。事件循环，周而复始，一直执行。











        let btn = document.querySelector('button')
        btn.onclick = function () {
            // // 发送简单GET
            let url = 'http://www.liulongbin.top:3006/api/getbooks'
            axios.get(url, {
                params: { bookname: '天行健' }
            }).then(function (res) {
                console.log(res.data.data);
            })






            // // 发送简单POST  不一样的数据类型，设置不一样的头信息
            //FormData对象需要设置      content-type: multypart/form-data
            //非form设置      content-type: application/x-www-form-urlencoded;
            let url = 'http://www.liulongbin.top:3006/api/addbook'
            let data = 'bookname=天行健&author=燕垒生&publisher=出版社出版社'
            axios.post(url, data).then(function (res) {
                console.log(res);
            })





            // // 发送GET
            axios({
                methor: 'get',
                url: 'http://www.liulongbin.top:3006/api/getbooks',
                params: { bookname: '天行健' }
            }).then(function (res) {
                alert(res.data.msg)
                console.log(res.data.data[0]);
            }).catch(function (res) {
                alert('获取失败')
            })



            // axios
            // 发送POST
            then()处理请求发送后接收到的数据
            catch ()处理无法发送引起的报错
            axios({
                method: 'post',
                url: 'http://www.liulongbin.top:3006/api/addbook',
                data: {
                    bookname: '天行健',
                    author: '燕垒生',
                    publisher: '出版社出版社'
                }
            }).then(function (res) {
                console.log(res);
                if (res.data.status < 400 & res.request.readystate == 4) {
                    return alert(res.data.msg);
                }
                alert(res.data.msg);
            }).catch(function (err) {
                alert('添加失败')
            })
        }
    </script>
</body>





git

<body>
    <!-- git 命令方法 -->

    <!-- 设置账户密码 -->
    git config --global user.name ""
    git config --global user.email ""


    <!-- 基础操作: -->
    1. git init : 初始化git仓库;
    2. git add . : 创建或者修改文件，把文件添加到 暂存区;
    3. git commit -m "提交版本的描述信息" : 一定要在暂存区提交完成后，在提交到本地仓库.
    4. git status : 查看文件状态; (nothing to commit, 已经提交过，没有异常文件了.)
    5. git log/reflog -数值 --oneline : 打印提交日志;
    6. git reset --hard ID : 切换版本;

    <!-- 分支操作: -->
    1. git branch : 查看分支
    1. git branch -b: 创建分支
    2. git checkout 分支名称 : 切换分支
    3. git checkout -b 分支名称 : 创建并切换分支
    4. git merge 分支名称 : 合并分支


    <!-- 远程仓库: -->
    0. git push -u origin 分支; 向远程地址推送分支;
    1. git pull 地址 分支 ： 向远程地址拉去分支代码;(分支代码更新)

    2. git remote add origin ssh/https地址； 向变量中保存地址;
    3. git remote -v : 查看保存了哪些变量；
    4. git remote rm origin : 删除变量；
    5. git remote show 地址 : 这个地址下有哪些分支;

    6. git clone 地址 : 克隆项目；(无中生有)
    7. git checkout 分支 : 如果这个分支，远程地址存在，就创建并拉取代码;



    <!-- 创建邮箱 公钥私钥 -->
    ssh-keygen -t rsa -C "邮箱"




    <!-- 多人协作开发: -->
    1. git clone SSH/HTTPS地址 克隆仓库
    2. git pull origin 分支名称 拉取远程仓库分支里面最新的代码
    3. git remote show origin 查看远程仓库分支
    4. git checkout 远程分支 跟踪分支(主分支拉，跟踪分支拉取在切换)


    5. .gitignore 这个文件，可以忽略文件和文件夹，脱离git的管理;
    /demo.html
    前方写 / ,代表忽略根目录下的文件名
    test/
    后方写 / ,代表忽略叫test的文件夹类型



</body>




node.js第一天总结

<body>
    <script>
        // 执行文件:
        1.用黑窗口执行;
        2. node   文件名.js
        3.尽量在当前目录下执行(相对路径)
        4.绝对路径，在哪里都可以执行;
        5.上下可以调出历史命令，Tab可以补齐文件路径;


        // 导入文件
        require('文件地址')
        // 通过此命令导入文件
        // 文件地址 前缀./ 不能省略, 后缀格式可以省略

        module.exports = { 传入的数据 }
        // 被传文件需要加此命令传递数据




        // 模块的划分：
        1.自定义模块：用户自己创建的每个JS文件，都是自定义模块
        2.内置模块（核心模块）：Node安装后，即可使用的模块，Node环境自带。
        3.第三方模块：其他人或公司、组织开发的模块，发布到 npm 网站，我们需要下载使用的模块






        // 读取创建判断文件模块     const fs = require('fs');
        内置模块 fs
        const fs = require('fs');

        读取内容 fs.readFile()
        写入内容 fs.writeFile()
        判断文件 fs.access()




        const fs = require('fs');
        // 读取文件
        fs.readFile('./txt/1.txt', 'UTF8', (err, txt) => {
            // err代表错误信息,txt代表读取到的内容
            // // 如果读取到文件, err是null, txt是读取到的内容;
            // 如果读取不到文件, err是对象, txt是undefined;
            // err 中有 name, 有 message;
            if (err) {
                return console.log("文件读取错误: " + err.message);
            }
            // 读取成功
            console.log("文件读取成功, 内容: " + txt);
        });
        console.log('我是同步代码,写道读取文件之后了...');// 注意: 读取文件是异步操作, 要在同步代码后面执行

        // 写入
        fs.writeFile('./txt/2.txt', '222', err => {
            // err: 写入成功返回 null, 写入失败返回 对象;
            if (err) {
                return console.log('写入失败，原因是: ' + err.message);
            }
            // 写入成功
            console.log('恭喜您，写入内容成功！');
        });
        // 注意: 写入文件，如果文件不存在就创建文件，但是文件夹不存在就报错;文件如果存在，就会出现内容的覆盖！

        // 判断
        fs.access('./txt/3.txt', fs.constants.F_OK, err => {
            fs.constants.F_OK或不填，表示判断文件是否存在；
            fs.constants.R_OK表示判断文件是否可读；
            fs.constants.W_OK表示文件是否可写；
            // 判断
            if (err) {
                return console.log('文件不存在！');
            }
            // 成功提示
            console.log('文件存在！');
        });



        // path模块 获取文件名称和地址
        1.path.extname(url); 获取最后的文件名的后缀名
        2.path.basename(url); 最后的文件名;
        2.path.basename(ur, '.后缀'); 最后的文件名 + 后缀名;
        // 定义绝对路径
        // 文件所在绝对路径     当前的文件的绝对路径
        __filename
        // 文件夹所在的绝对路径  当前文件夹的绝对路径
        __dirname
        // 手动拼接路径繁琐,兼容性有问题;
        __dirname + '/文件夹/文件名'



        // 定义一个相对路径
        相对路径，相对的是执行js文件所在的位置；不是文件本身所在的位置
        let url = './txt/1.txt'




        // 解码编码字符串模块
        querystring
        const querystring = require('querystring');

        // 解码 转换为 a=1&b=2&c=3 格式
        querystring.stringify(obj)

        // 解码 转换为对象
        querystring.parse("a=1&b=2&c=3")



        // 协议: 协议就是网络通讯过程当中。应当遵循的一种格式。
        //      http / https    请求报文、响应报文; (请求行/请求头/空行/请求体)
        // 域名/IP: 根据域名/IP可以在网络中查找到一台电脑。
        //      127.0.0.1    localhost
        // 端口: 一台电脑端口号: 0~65535    0~1023固定端口;   1024~65535动态端口;
        //      端口可以确定哪一个具体的程序;(一个端口只能由一个程序监听)





        // 网络请求相关模块
        http    // 写法固定

        // 1.导入内置模块
        const http = require("http");
        // 2.创建服务器实例
        const server = http.createServer()
        // 3.绑定请求事件
        server.on('request', (req, res) => {
            res.end('I am a Man !');
        });
        // 4.监听端口   0~65535
        server.listen(8888, function () {
            console.log('服务器已开启, 请访问: http://localhost:8888');
        });
        // 通过 req 可以获取到请求相关的信息
        // 通过 res.end(输出的内容可以是标签) 可以做出响应处理
        // localhost 和 127.0.0.1 这种数字IP 一样都是本地IP,仅自己可以访问



        //  res.end写标签需要设置头信息
        res.setHeader("Content-Type", "text/html; charset=utf8");
        res.end("<h2>404 Not Found ! 您所访问的网站，不在这个星球~</h2>");


    </script>
</body>







node.js第二天总结

<body>
    <script>
        // 数据库
        // 查询表格 select
        select * from user
        // * 此位置可写查找的属性,写*代表查找所有
        例: select username, password from user
        // 查找 username和password 的内容
        // user 代表查找的表格文件
        // user 后面可以跟 where id = 1 控制查询条件


        // 添加表格 insert into    // set设置命令
        insert into 表格名 set username = '阿瞒', password = '987987'


        // 修改表格 update   // where 条件判断
        update user set sex = '外星人'  where age > 15 and age < 35;


        // 删除表格 delete
        delete from user where id = 2; 这种真的删除用得少, 一般不会真删除
        update user set sex = '已删除' where id = 1;
        select * from user


        and // 与
        or  // 或









        // node.js
        // 查看版本号
        npm - v
        // 初始化
        npm init - y
        // 下载
        npm i 下载的模块名@版本号
        // 全局下载
        npm  i - g  下载的模块名@版本号
        // 卸载
        npm uninstall
        // 引入
        const moment = require('moment')
        // 查看时间
        moment().format('YYYY-MM-DD HH:mm:ss')



        // moment   日期使用
        1.  初始化文件夹: npm  init - y
        2.  下载第三方包: npm  i  moment@2.29.1
        3.导入模块
        const moment = require("moment");
        4.使用 api
        let d2 = moment().format('YYYY-MM-DD HH:mm:ss'); // 格式化之后的日期对象
        console.log(d2);

        // moment   指定日期
        let d = new Date('1999/11/11');
        let d3 = moment(d).format('YYYY-MM-DD HH:mm:ss');
        console.log(d3);


        // mysql    操作数据库
        1. 下载: npm  i  mysql@2.18.1
        2. 导入
        const mysql = require("mysql");
        3. 创建mysql连接对象
        const conn = mysql.createConnection({
            host: '127.0.0.1', // host 属性定义连接哪台服务器
            user: 'root', // user 属性定义用户名
            password: 'root', // password 属性定义密码
            database: 'my_database',  // database 属性定义数据库名字;
        });
        4.连接数据库
        conn.connect();
        5.操作
        conn.query('select 3', (err, results) => {
            // err代表sql语句语法出现了错误
            if (err) {
                return console.log(err.message);
            }
            // 没有问题，就输出结果
            console.log(results);
        });
        // 6.断开
        conn.end();





        // 封装增删改查 封装数据库
        // 导出 封装
        function fn(sql, callback) {
            // 函数每次调用有两处不同，sql和回调函数
            // 导入
            const mysql = require('mysql');
            // 创建
            const conn = mysql.createConnection({
                host: 'localhost',
                user: 'root',
                password: 'root',
                database: 'my_database'
            });
            // 连接
            conn.connect();
            // sql操作
            conn.query(sql, callback); // 把函数作为参数传递并调用，这个函数就是回调函数
            // 断开
            conn.end();
        }
        // 把这个函数导出，别人导入这个文件，才能用这个函数
        module.exports.fn = fn;
        或者: module.exports = fn;
        或: module.exports = function () { }  //直接定义最好用




        // 导入 数据库操作文件(自定义模块)
        const db = require('./database/index');
        db.fn('select * from user', (err, results) => {
            // 判断sql
            if (err) return console.log(err.message);
            // 成功提示
            console.log(results);
        });
    </script>
</body>







node.js第三天总结

<body>
    <script>
        // nrm
        一个npm包，用npm换源每次都要写一堆非常麻烦，nrm可以轻松解决这个问题


        // 安装
        使用npm命令进行全局安装：npm install nrm - g

        // 列出所有
        nrm - h

        // 查看版本
        nrm - V

        // 显示所有源
        nrm ls

        // 切换源
        nrm use 源名

        // 添加源
        rm add baidu www.baidu.com

        // 删除源
        nrm del baidu






        // 生成token    

        // 下载     install 可以简写为 i
        npm  install  jsonwebtoken@8.5.1

        // 导入
        const jwt = require('jsonwebtoken');

        // 设置token
        const token = "Bearer " + jwt.sign(
            // 生成: sign()有三个参数;
            //    第一个: 要保存到 token 中的对象;
            //    第二个: 加密字符串;
            //    第三个: 对象类型定义有效时长;
            // jwt.sign( {}, '', {} );
            { id: 111, username: 'zhangsan' }, // 加密的对象，一般三五个属性足以，id基本是必须的;
            'lvchao ^_^ !', // 加密字符串随意
            { expiresIn: "360h" }, // 360是十五天 24*15 // 有效时长，随公司规定
        );
        console.log(token);





        // require()加载机制
        判断缓存中有没有正在加载的模块，如果有，使用缓存中的内容，如果没有，那么表示第一次加载，加载完会缓存

        判断模块名有没有带路径（./）
        模块名中有路径，加载自定义模块（自己写的文件）
        const xx = require('./xx')
        1.优先加载同名文件，加载一个叫做 xx 的文件
        2.再次加载js文件，加载 xx.js 文件
        3.再次加载json文件，加载 xx.json 文件

        如果上述文件都没有，则报错 “Cannot find module './xx'”

        模块名没有路径，优先加载核心模块，如果没有核心模块，则加载第三方模块

        加载第三方模块的查找方式
        优先在当前文件夹的node_modules里面查找第三方模块
        在当前文件夹的上级目录的node_modules里面查找第三方模块
        继续向上层文件夹查找第三方模块







        // express
        // 导入
        const express = require('express')
        // 创建
        const app = express();
        // 设置请求方式和资源路径对应的处理
        app.get('/api/getbooks', (req, res) => {
            //  这个方法，只能发送字符串，不能发送对象，发送汉字需要设置头信息;
            // res.end(); 这个方法是 http 模块赋予我们的，功能比较单一;
            // res.send(): 这个方法是 express 封装之后的，他可以发送对象，而且发送汉字不用设置头信息;
            res.send({
                status: 0,
                message: '获取图书列表成功'
            });
        });
        app.post('/api/addbook', (req, res) => {
            res.send({
                status: 0,
                message: '添加图书成功'
            })
        });
        // 监听
        app.listen(80, function () {
            console.log('http://localhost:80');
        })






        // 大事件接口
        res.send    可生效的代码中只能由一行res.send


        // 创建
        const express = require('express');
        const app = express();
        // 要想接受 application/x-www-form-urlencoded 请求体参数，要如下设置
        app.use(express.urlencoded({ extended: false }));// 设置了这句话，req上就有body属性了
        // 书写注册的请求方式，资源路径和处理函数
        app.post('/api/reguser', (req, res) => {
            // // 没有上面的设定，就没有下面的 req.body；
            // console.log(req.body);
            // 先把用户名和密码结构出来，方便后面操作;
            let { username, password } = req.body;
            // 导入数据库模块，根据用户名查询，判断是否查到具体的数据; 
            const db = require('./database/index');
            // 导出的本身就是一个函数
            db(`select * from user where username = "${username}"`, (err, results) => {
                // 判断sql
                if (err) return res.send({ status: 1, message: err.message });
                // 判断结果，如果查到一条相同的用户名，都不允许注册
                if (results.length >= 1) return res.send({ status: 1, message: "用户已存在" });
                // 成功后提示 - 还没有真正的添加！
                // 添加的sql操作，要写到查询sql操作的里面
                let sql = `insert into user set username = "${username}", password = "${password}"`;
                db(sql, (err, results) => {
                    // 判断sql
                    if (err) return res.send({ status: 1, message: err.message });
                    // 判断影响的行数
                    if (results.affectedRows !== 1) return res.send({ status: 1, message: "注册失败！" });
                    // 成功提示
                    res.send({
                        "status": 0,
                        "message": "注册成功！"
                    });
                })
            });
            // // Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
            // // 两次send()就会报上名的错误
        });
        // 监听
        app.listen(3006, function () {
            console.log('http://localhost:3006');
        });
    </script>
</body>









node.js第六天总结
<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- jsonp请求 解决跨域问题-->
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="http://localhost:8888/get/jsonp?callback=lvchao"></script>
    <script>
        // 同源策略
        编程中的同源，比较的是两个url是否同源。
        主要看下面三个方面：
        1.协议是否相同（http  https  file）
        2.主机地址是否相同（www.xxx.com  127.0.0.1）
        3.端口（0~65535）（http默认端口是80；https默认端口是443；MySQL默认端口3306）

        协议、主机地址、端口组成一个“源”。
        如果两个url的协议、主机地址、端口都相同，那么这两个url是同源的，否则就是非同源。
        如果非同源，那么以下三种行为会受到限制：

        1.Cookie 无法操作
        2.DOM 无法操作
        3.Ajax请求无效 （请求可以发送，服务器也会处理这次请求，但是响应结果会被浏览器拦截）

        违反了同源策略的请求，叫做 跨域请求 。







        就是通过script标签发起请求, src写了一个地址，该地址给我们响应了一个字符串
        原生Js直接发送请求即可
        使用jQuery, ajax需要加一个属性 dataType: 'jsonp', 才能将设置为设置为jsonp请求; 不然会因为跨域而报错
        // 例
        $.ajax({
            method: 'GET',
            url: 'http://localhost:8888/get/jsonp',
            // 加一个属性dataType，就可以设置为jsonp请求;
            // jsonp请求是通过script标签发送的，不是通过xhr对象发送的;
            dataType: 'jsonp',  // 设置jsonp 发送方式
            success: function (res) {
                console.log(res);
            }
        });




        // !!前端 设置一全局函数，等待将来其他文件调用,并且在下方写一个script将函数名赋值并发送给后端
        function zhang(aaa) {
            console.log(aaa);
        }
        // !!后端   在后端接收书写路由
        app.get('/get/jsonp', function (req, res) {
            // 发送js代码
            // res.send("var num='我是后端定义的全局变量';");
            // res.send("alert('后端返回的数据！')");
            // 去执行前端有的全局函数
            // res.send('lvchao({name: "张三", age: 18})');
            // 把函数名，传给我
            let fnName = req.query.callback;
            setTimeout(function () {
                res.send(fnName + '({name: "李四", age: 21})');
            }, 1000);
        });
    </script>
    <!-- 自己创建一个script标签，模拟ajax请求，这就是jsonp的原理 -->
    <script src="http://localhost:8888/get/jsonp?callback=zhang"></script>








    CORS

    由于XHR对象被W3C标准化之后，提出了很多XHR Level2的新构想，其中新增了很多新方法（onload、response....）和CORS跨域资源共享。浏览器升级后开始支持CORS方案，从IE10开始支持。
    CORS方案，就是通过服务器设置响应头来实现跨域**。
    CORS才是解决跨域的真正解决方案。

    - 前端需要做什么？
    - 无需做任何事情，正常发送Ajax请求即可。
    - 后端需要做什么？
    - 需要加[响应头](https://developer.mozilla.org/zh-CN/docs/Glossary/CORS) 。或者使用第三方模块 **cors** 。

















    <!-- 防抖节流 -->
    <!-- 防抖   减少访问量,减轻服务器压力-->
    <script>
        let timer = 0;
        let input = document.querySelector('input')
        //  输入事件：input ;  键盘弹起事件：keyup;
        input.onkeyup = function () {
            // 用输出值，模拟向后端发送请求
            // console.log(this.value);
            // 防抖策略：利用定时器实现后端请求的发送，规定时间内再次出发，取消掉原有的请求;
            // 去掉原有定时器
            clearTimeout(timer);
            timer = setTimeout(() => {
                // 定时器里面的this指向window，为了获取事件源，改为使用箭头函数,this就可以指向上级事件源
                console.log(this.value);
            }, 1500);
        }
    </script>




    <!-- 节流 -->
    <!-- 例     小鸟跟随鼠标案例 -->
    <img src="./angel.gif" style="position: fixed;">
    <script>
        // 用原生js实现 - 鼠标在页面上移动，img跟随移动。
        let img = document.querySelector('img');
        // 全局变量接收定时器
        let timer = 0;
        document.onmousemove = function (e) {
            // 判断，上一次的定时器，有没有执行完毕，执行完毕在能执行下一次！
            if (timer !== 0) {
                return; // timer不等于0，就说明上一个定时器还没有执行完毕！
            }
            // 获取鼠标在页面中的坐标
            // console.log(e.pageX, e.pageY);
            timer = setTimeout(function () {
                console.log(1);
                img.style.top = e.pageY + 'px';
                img.style.left = e.pageX + 'px';
                // 执行完毕，一定要记得把timer设置为0；
                timer = 0;
            }, 20);
        }
    </script>







    <!-- module -->
    <script>
        // import 导入文件
        // // 方法1:  前缀后缀都不能省略
        import o1 from './02_导入文件.js';
        console.log(o1);
        // // 方法2: 前缀后缀都不能省略
        import { n1, s1, fn } from './02_导入文件.js';
        console.log(n1, s1, fn);
        import { n1, s1, fn as f1 } from './02_导入文件.js';// 可以赋值给别的变量,用as赋值
        console.log(n1, s1, f1());
        // 方法3: 前缀后缀都不能省略
        import './02_导入文件.js';// 要的是整个功能，不是返回的数据;






        // export 导出
        // 方法1: 导出单个
        let obj = { name: '张三', age: 18 };
        export default obj;
        // 方法2：导出多个
        export const n1 = 123;
        export let s1 = 'xyz';
        export const fn = function () {
            console.log('我是函数fn');
        }
        // 方法3: 导出所有  强调的是功能，不是导出的数据;
        console.log('去全聚德，吃一次烤鸭...');
        export default "鸭架子";
    </script>





    <!-- promise -->
    <script>
        // promise语法
        // es6 导入 fs 模块
        import fs from 'fs';
        // promise对象语法 - 参数是回调函数
        let p1 = new Promise((resolve, reject) => { // Promise这个构造函数里面，一定要放入异步代码！
            fs.readFile('./txt/a1.txt', 'utf8', (err, data) => {
                // resolve操作成功要他处理, reject操作失败用他处理
                if (err === null) {
                    resolve(data);
                } else {
                    reject(err);
                }
            });
        });
        // promise取值
        // 在 promise 对象身上，有两个方法，then()处理成功，catch()处理失败;
        p1.then((res) => {
            console.log(res);
        }).catch((err) => {
            console.log("文件读取失败: " + err.message);
        });




        // 解决回调地狱
        // 创建三个 promise 对象，每个对象读取一个文件
        let p1 = new Promise((resolve, reject) => {
            // 读取文件
            fs.readFile('./txt/a.txt', 'utf8', function (err, data) {
                resolve(data); // 只考虑成功，把成功的值跑出去；不考虑失败了
            });
        });
        let p2 = new Promise((resolve, reject) => {
            fs.readFile('./txt/b.txt', 'utf8', function (err, data) {
                resolve(data);// 只考虑成功
            });
        });
        let p3 = new Promise((resolve, reject) => {
            fs.readFile('./txt/c.txt', 'utf8', function (err, data) {
                resolve(data);// 只考虑成功
            });
        });
        // 按照顺序读取，解决回调地狱问题
        p1.then(res => {
            console.log(res);
            return p2; // 这个箭头函数的返回值，会赋值给第一个then();第二个then就是p2调用的
        }).then(res => {
            console.log(res);
            return p3;// 这个箭头函数的返回值，会赋值给第二个then();第三个then就是p3调用的
        }).then(res => {
            console.log(res);
        });
        // 直接读取 - 没有先后顺序
        p1.then(res => console.log(res)); // 不考虑catch();
        p2.then(res => console.log(res)); // 不考虑catch();
        p3.then(res => console.log(res)); // 不考虑catch();


        // promise同步异步
        // 同步
        console.log(1);
        // 创建promise对象 - 同步
        let p1 = new Promise((resolve, reject) => {
            resolve(111);
            console.log(2);
            console.log(3);
        });
        // 调用then(); - 异步执行
        p1.then(res => {
            console.log(res);
            console.log(4);
        });
        // 最后输出
        console.log(5);
    </script>




    <!-- 模块 -->
    <script>
        和fs一样都是可以用来读取文件
        fs 模块的返回值为 undefined
        then - fs 模块的返回值为 Promise对象


        // then-fs解决回调地狱
        // es6导入  
        import thenfs from 'then-fs';
        // then-fs    mysql    axios  等现有模块，返回的是Promise对象;
        thenfs.readFile('./txt/a.txt', 'utf8')
            .then(res => {
                console.log(res);
                return thenfs.readFile('./txt/b.txt', 'utf8');
            }).then(res => {
                console.log(res);
                return thenfs.readFile('./txt/c.txt', 'utf8');
            }).then(res => {
                console.log(res);
            });
    </script>



    <!-- async   await -->
    <script>
        // async 是异步的意思; 可以用户修饰一个函数，写到 function 的前面;
        async function fn() {
            return '我是fn函数的返回值'
        }// async 返回值为Promise 对象





        // await
        1.await只能出现在异步函数中！
        2.await能停止代码执行，让后面的同步代码，先执行;
        3.await后面跟随的必须是一个promise对象;
        4.await返回的是: Promise对象中的then()中的回调函数中的参数res(返回值);

        // 自定义一个异步函数
        async function f1() {
            return '函数f1';
        }
        async function fn() {
            // f1()返回的就是一个Promise对象;
            // await返回的是: Promise对象中的then()中的回调函数中的参数res;
            let aaa = await f1();
            console.log(aaa);
        }
        fn();
        // 最低端写一个同步代码
        console.log('同步代码');








        // async + await解决回调地狱
        // 还是需要 then-fs 模块;
        import thenfs from 'then-fs';
        // 定义一个异步函数, 函数里面就可以使用 await 了
        async function fn() {
            // 扩展: try ... catch ...  尝试执行某些可能出问题的代码，catch捕获异常
            try {
                // 用 await 关键字，剥离出 Promise对象中的then()中的回调函数中的res
                let t1 = await thenfs.readFile('./txt/a.txt', 'utf8');
                console.log(t1);
                let t2 = await thenfs.readFile('./txt/bb.txt', 'utf8');
                console.log(t2);
                let t3 = await thenfs.readFile('./txt/c.txt', 'utf8');
                console.log(t3);
            } catch (err) {
                console.log("文件读取出现异常: " + err.message);
            }
        }
        // 调用函数
        fn();
        console.log('我是同步代码');
    </script>




    <!-- 宏任务微任务 -->
    <script>
        // 异步 - 宏任务
        setTimeout(() => {
            //执行后 回调一个宏事件
            console.log('1')
        }, 0);
        // 同步
        console.log('2');
        // 构造函数中的参数是同步，then()的参数是异步; - 微任务
        new Promise((resolve) => {
            console.log('3');
            resolve()
        }).then(() => {
            console.log('4');
        }).then(() => {
            console.log('5')
        });
        // 同步
        console.log('6')
    // 2 3 6 4 5 1
    // 总结: Promise里面的then()虽然是异步任务，但是，他会比其他的异步任务优先执行，因为他是微任务！
    </script>
</body>











webpack

<body>
    <!-- 降级处理
        ES6模块导入浏览器无法直接被识别,需要降级处理-->
    <!-- 1. 需要引入babel文件：为了处理ES6模块导入导出 -->
    <script src="./babel.min.js"></script>
    <!-- 2. 告诉浏览器 处理哪个代码-->
    <script type="text/babel">
        import zs from "./index.js"; console.log(zs);
    </script>
    <!-- 3. 需要用IP+port方式 打开才能降级处理 -->




    <script>
        // yarn // 前端ES6模块化：未来工作模式 

        // 初始化
        yarn  init
        // 下载
        yarn  add  下载的模块名
        // 删除
        yarn  remove  删除的模块名
        // 执行自定义命令   build代表 配置中scripts中定义的属性命令
        yarn  build
        // 自定义命令   在package.json文件中添加设置如下
        "scripts": {
            "build": "webpack"
        }




        // 修改入口出口
        1.建一个webpack.config.js文件
        2.// yarn add webpack  webpack-cli
        配置文件如下:
        const path = require('path');
        path.join();
        module.exports = {
            // entry：入口l找哪个前端文件作为入口文件；
            entry: './aa/app.js',
            // output：出口
            output: {
                // 输出的路径   默认为 dist
                path: path.resolve(__dirname, 'bb'),
                // 最终打包后文件名 默认为 main.js
                filename: 'main.js',
            },
        };





        // 打包html
        // 下载依赖包
        // yarn add html-webpack-plugin -D
        // webpack.config.js 中添加代码
        const HtmlWebpackPlugin = require('html-webpack-plugin');
        const path = require('path');
        module.exports = {
            // 插件：把哪个文件作为最终打包编译后前端 HTML文件输出
            plugins: [new HtmlWebpackPlugin({
                template: "./public/index.html"
            })],
        };





        // 打包css
        先将css代码引入js文件中     import "css文件路径"
        // 下载依赖包
        // yarn add style-loader css-loader -D
        // webpack.config.js 中添加代码
        const HtmlWebpackPlugin = require('html-webpack-plugin')
        module.exports = {
            // ...其他代码
            module: {
                rules: [ // loader的规则
                    {
                        test: /\.css$/, // 匹配所有的css文件
                        // use数组里从右向左运行
                        // 先用 css-loader 让webpack能够识别 css 文件的内容并打包
                        // 再用 style-loader 将样式, 把css插入到dom中
                        use: ["style-loader", "css-loader"]
                    }
                ]
            }
        }





        // 打包less
        将 less 代码引入js文件  import "less文件路径"
        // 下载依赖包
        // yarn add less less-loader -D
        // webpack.config.js 中添加代码
        module: {
            rules: [ // loader的规则
                // ...省略其他
                {
                    test: /\.less$/,
                    // 使用less-loader, 让webpack处理less文件, 内置还会用less翻译less代码成css内容
                    use: ["style-loader", "css-loader", 'less-loader']
                }
            ]
        }




        // 打包压缩代码
        1.准备环境初始化
        2.下载 webpack 和 webpack - cli
        3.修改build命令 "build": "webpack"
        4.建立一个 src 文件夹, 在这里写js文件和css
        5.建立一个 public 文件夹, 在这里写html
        6.将所有文件引入入口js文件中 默认 index.js
        7.yarn build    生成一个dist文件夹, 里面会有压缩好的代码
    </script>
</body>







vue 第一天总结


<!-- 插值表达式 -->
1.{{输出的属性名}}
2.{{ obj.age >= 18 ? "成年" : "未成年" }}



<!-- vue自定义属性  一一对应-->
1.v-bind:href="绑定的属性"
2.:href="绑定的属性"
例: <img :src="src" alt="" />



<!-- vue事件 -->
@事件="事件执行函数" 或 v-on:事件="事件执行函数"
例: <button @click="fn3">数组去重</button>

@input :input事件是实时监控的，每次输入都会调用
@click :点击事件
@change :输入框改变则触发
@keyup :键盘按下触发
@blur :失去焦点的时候触发


<!-- 修饰符:  -->
<button @click.stop="fn4">阻止冒泡</button>
<a @click.prevent="fn4" href="http://www.baidu.com">阻止默认</a>
<!-- 输入框事件 -->


<!-- 键盘事件 -->
可以选定那个键的事件,如果不指定,默认所有键都可以触发
@keyup="函数名"
@keydown="函数名"
@keyup.enter="函数名"
@keydown.esc="函数名"
例: <input type="text" @keydown.enter="fn4" />








<!-- vue创建标签内容 -->
v-text 和 v-html
v-text="创建内容绑定的属性" 不会识别标签
v-html="创建内容绑定的属性" 会识别标签并添加到html中
例:
<p v-text="属性名"></p>
<p v-html="属性名"></p>



<!-- vue显示隐藏 -->
v-show 和 v-if 以条件是否为true来判定显示隐藏
v-show 操作display属性,设置true和false来设置隐藏显示
v-if 并非显示和隐藏,而是创建和删除,最好少用,对于浏览器性能会有影响
例:
<p v-show="control">这里是 v-show</p>
<p v-if="control">这里是 v-if</p>



<!-- vue循环 -->
v-for 循环生成本标签
<li v-for="(items, index) in array" :key="index">
    <span>索引:{{ index }}</span>
    <span>内容:{{ items }}</span>
</li>





<!-- vue双向绑定 v-model-->
v-model 将所在标签的变化实时传递改变代码,并根据改变后的代码更改变化的页面元素
多选中可以以此实现,全选,获取数据
<!-- 获取数据 -->
v-model="定义的数组名"
<!-- 全选 -->
v-model="定义的布尔类型属性名"
<!-- 单选 -->
v-model="定义的选中元素属性名"
<!-- 下拉 -->
v-model="默认选中的下拉元素的属性"
<!-- lazy:懒 -->
类似于 文本框的change事件 失去光标的时候触发
<!-- number -->
转化数据类型为数字类型
<!-- trim -->
去除两边的空格








<!-- 获取事件对象 -->
调用函数中,既要传递参数,又要获取事件对象 $even
<button @click="fn3(88, $event)">baidu</button>








<!-- 下载vue -->
yarn global add @vue/cli 或者 npm install -g @vue/cli

<!-- 建立vue脚手架 --> vue create是建立, vuecli-demo是文件夹名,可以自定义英文名
vue create vuecli-demo

<!-- 开启vue服务器 -->
yarn serve



<!-- 建立一个 vue.config.js 文件 -->
<!-- 配置端口,关闭vue代码格式检查 -->
module.exports = {
devServer: {
// 设置端口
port: 8080,
open: true
},
<!-- 关闭vue代码格式检查 -->
lintOnSave: false
}




vue初始化 APP文件
<template>
    <div id="app">
        对应的html结构
    </div>
</template>
<script>
    export default {
        data() {
            return {
                对应的属性变量
            };
        },

        methods: {
            对应的方法
        },
    };
</script>
// css样式
<style scoped>
    #app {
        对应的css样式
    }
</style>










<!-- 功能命令 -->
<template>
    <div id="app">
        <h1>1-插值表达式</h1>
        <p>直接显示：{{ msg }}</p>
        <p>对象属性：{{ obj.name }}</p>
        <!-- vue语法：{{ 提高 区分数据类型}} -->
        <p>三元表达式：{{ obj.age >= 18 ? "YES" : "NO" }}</p>



        <h1>2-v-bind：给标签绑定属性</h1>
        <a v-bind:href="href">跳转1</a>
        <a :href="href" :aaa="src">跳转2</a>
        <img :src="src" alt="" />



        <h1>3-v-on：@ 基本使用 注册事件</h1>
        <button v-on:click="numb = 20">按钮1</button>
        <button v-on:click="fn">按钮2</button>
        <button v-on:click="fn1(20)">按钮3</button>
        <button @click="fn1(30)">按钮4</button>


        <h1>4-v-on：获取事件对象</h1>
        <a @click="fn2" href="http://www.baidu.com">baidu</a>
        <!-- 既要传入实参，又要获取事件对象 $event -->
        <button @click="fn3(88, $event)">baidu</button>



        <h1>5-v-on：修饰符</h1>
        <!-- 事件执行函数：可以被多个标签绑定 -->
        <a @click.prevent="fn4" href="http://www.baidu.com">阻止默认</a>
        <button @click.stop="fn4">阻止冒泡</button>
        <input type="text" @keydown.enter="fn4" />



        <h1>6-v-on：执行函数内部：this</h1>
        <span>{{ numb }}</span>
        <button @click="fn5">btn-this</button>



        <h2>反转字案例：</h2>
        <p>{{ msg }}</p>
        <button @click="fn6">反转</button>



        <h1>【7-v-model：最能体现数据双向绑定！！】</h1>
        <p>
            输入框和文本域：
            <input type="text" v-model="iptstr" /><br />
            {{ iptstr }}<br />
            <textarea v-model="iptstr"></textarea>
        </p>
        <p>
            <!-- 密码：<input type="password" v-model="pwd"> -->
            {{ pwd }}
        </p>
        <p>
            下拉选择：
            <select v-model="sel">
                <option value="北京市">北京</option>
                <option value="南京市">南京</option>
                <option value="天津市">天津</option>
            </select>
        </p>
        <p>
            多选框1：看变量
            初始化为数组，点击多选框的时候，变量把选中value值添加到数组
            <br />
            <!-- v-model重要：-->
            <input type="checkbox" v-model="arr" value="抽烟" />抽烟
            <input type="checkbox" v-model="arr" value="喝酒" />喝酒
            <input type="checkbox" v-model="arr" value="写代码" />写代码
        </p>
        <p>
            多选框2：看变量 初始化为boolean，整体是否选中
            <br />
            <!-- v-model重要：-->
            <input type="checkbox" v-model="key" value="抽烟" />抽烟
            <input type="checkbox" v-model="key" value="喝酒" />喝酒
            <input type="checkbox" v-model="key" value="写代码" />写代码
        </p>

        <p>
            单选：
            <br />
            <input type="radio" value="男" name="sex" v-model="gender" />男
            <input type="radio" value="女" name="sex" v-model="gender" />女
        </p>
        <button @click="fn7">submit</button>


        <h1>7-v-model：修饰符</h1>
        <!-- <input type="text" v-model="a">+<input type="text" v-model="b">={{a*1+b*1}} -->
        <br />
        <input type="text" v-model.number="a" />+<input type="text" v-model.number="b" />={{ a + b }}

        <br />
        <input type="text" v-model.trim="name" />{{ name }}
        <br />
        <!-- lazy:懒 -->
        <!--   input  change  input事件 -->
        <input type="text" v-model.lazy="aaa" />{{ aaa }}




        <h1>8-v-text v-html</h1>
        <p v-text="spanstr"></p>
        <p v-html="spanstr"></p>



        <h1>9-v-show v-if</h1>
        <button @click="control = !control">{{ control ? "收起" : "展开" }}</button>
        <p v-show="control">我是一个p标签，我被show控制了！</p>
        <p v-show="control">我是一个p标签，我被show控制了！</p>
        <p v-show="control">我是一个p标签，我被show控制了！</p>
        <p v-show="control">我是一个p标签，我被show控制了！</p>
        <!-- <p v-if="control">我是一个p标签，我被if控制了！</p> -->

        <!-- 频繁通过控制变量：让某个标签显示或隐藏  使用v-show -->
        <h1>10-v-for</h1>
        <ul>
            <!-- 技巧：让谁循环，就把v-for在哪个标签上就OK -->
            <li v-for="(item, index) in array" :key="index">
                {{ index }} ------> {{ item }}
            </li>
        </ul>
        <ul>
            <!-- 技巧：让谁循环，就把v-for在哪个标签上就OK : (随便起) -->
            <li v-for="(val, key) in some" :key="key">{{ key }} ------> {{ val }}</li>
        </ul>

        <ul>
            <li v-for="(item, index) in stuArr" :key="index">
                {{ item.name }} {{ item.sex }} {{ item.hobby }}
            </li>
        </ul>
    </div>
</template>

<script>
    export default {
        //  1.初始化数据  固定语法
        data() {
            return {
                // 初始化数据
                msg: "133-day02-vue",
                obj: {
                    name: "zs",
                    age: 18,
                },
                href: "http://itcast.cn",
                src: "https://img2.baidu.com/it/u=3960470193,627689163&fm=26&fmt=auto&gp=0.jpg",
                numb: 10,
                iptstr: "我是输入框的一个数据",
                pwd: "000000",
                sel: "天津市",
                arr: ["写代码"],
                key: true,
                gender: "男",
                spanstr: "<span>我是HTML结构的字符串</span>",
                a: 0,
                b: 0,
                name: "zs",
                aaa: "----",
                control: true,
                array: [10, 20, 30, 40],
                some: {
                    a: "我是a属性的值",
                    b: "我是b属性的值",
                    c: "我是c属性的值",
                    e: "我是e属性的值",
                },
                stuArr: [
                    {
                        id: 1001,
                        name: "孙悟空",
                        sex: "男",
                        hobby: "吃桃子",
                    },
                    {
                        id: 1002,
                        name: "猪八戒",
                        sex: "男",
                        hobby: "背媳妇",
                    },
                ],
            };
        },

        //  2.页面执行函数
        methods: {
            fn() {
                console.log(1);
            },
            fn1(a) {
                console.log(a);
            },
            fn2(e) {
                // e属性 和方法；
                // e.preventDefault();
                // 阻止冒泡：当父子结构都注册同样的事件，触发子元素，会把父级的函数也会执行！
                // e.stopPropagation();
            },
            //
            fn3(numb, e) {
                console.log(numb, e);
            },
            fn4() {
                console.log(1);
            },
            fn5() {
                // console.log(this.numb);
                this.numb++;
                this.obj.name = "***********************************";
            },
            fn6() {
                // 1  干啥？操作某个数据  this.msg
                // 2. 学我学过反转 是数组的方法
                // 3. 现在 字符串
                let arr = this.msg.split("");
                arr = arr.reverse();
                this.msg = arr.join("");
            },
            fn7() {
                // 如何拿数据？
            },
        },
    };
</script>









vue 第二天总结
<template>
    <div id="app">
        vue class vue样式绑定
        <!-- data 中定义aa: true, -->
        <p :class="{bgc_red:aa}"></p>
        <p :class="{bgc_red:aa,box:bb}"></p>



        vue style 绑定
        <!-- data 中定义some: "blue" -->
        <div :style="{color:some}">style绑定</div>




        删除数组指定对象:
        <!-- fn(id){
            let i;
            this.arr.filter((items,index)=>{
                if(items.id==id){
                i=index
            }
        }) 
        this.arr.splice(i,1)-->





        <!-- 过滤器：vue功能函数，帮助我们处理数据的显示格式； -->

        局部：只能当前文件内使用，其他组件不能使用！
        <div>局部过滤器：{{msg|up}}</div>
        <!-- export default 中定义:
        filters: {
            up(str) {
              return str.toUpperCase();
            },
          }, -->

        全局 写入入口文件中,所有引入的组件都可以用
        <div>全局过滤器：{{msg|fly}}</div>
        <!-- 在入口文件中写:
        Vue.filter("fly", (str) => {
            return "******__" + str + "__******";
        }); -->







        过滤器转化时间格式
        可以下载 moment 模块
        在script标签中引入moment模块
        <script>import moment from "moment";</script>
        <!-- 
        list: [
            { id: 103, name: "头发", price: 19900, time: new Date("2020-12-12") },
        ], -->
        <!--
         filters: {
            formate(time) {
                return moment(time).format("YYYY-MM-DD hh-mm-ss");
            },  
        },
        -->






        计算属性 computed
        计算属性场景：当某个结果的值 是 依赖于其他 数据或者变量的值
        <!-- 插值：多次执行，占用内存 -->
        <h1>插值： {{ a + b }}</h1>
        <h1>插值： {{ a + b }}</h1>

        <!-- getSum()：多次执行，占用内存 -->
        <h1>methods： {{ getSum() }}</h1>
        <h1>methods： {{ getSum() }}</h1>

        <!-- computed：执行一次，结果不再变化，使用缓存结果 -->
        <h1>computed： {{ sum }}</h1>
        <h1>computed： {{ sum }}</h1>

        <!-- computed:{
            // 【死记住】
            1、简单写法：目前只能被其他数据计算处理，视图不能改变它！视图一改变报错！
            // sum(){  
            //   return true;
            // }
        
            2.完整写法 既要被其他数据计算出来，又要通过视图可以改变它,语法都是固定
            sum:{
                结束计算后的执行
              set(val){
                // val get计算改变后的返回值；
                console.log(val);
              },
                计算函数
                get() {
                    return a+b;
                }
            }
          } -->




        监听器
        <!-- watch: {
            "要侦听的属性名": {
                immediate: true, // 立即执行监听函数
                deep: true, // 深度侦听复杂类型内变化
                handler (newVal, oldVal) {  // 执行的函数
                    
                }
            }
        } -->




        <!-- call()、apply()、bind() 都是用来重定义 this 的指向的 -->
        call(设定的this指向,实参,实参,实参,实参)
        call()传递的参数由逗号隔开

        apply(设定的this指向,[实参,实参,实参,实参])
        apply()传递的参数以数组形式写

        bind(设定的this指向,实参,实参,实参,实参)()
        bind()和call()一样,只不过是返回一个新数组需要再跟一个()自调用执行



    </div>
</template>




vue 第三天总结

<template>
    <!-- 组件 :  components:{'定义组件标签名',引入的组件名} -->
    局部组件 : 在引入文件中编写如下,仅可以在引入的文件中使用调用组件
    语法: 在引入的文件中编写如下
    <script>
        // 引入组件变量
        import Shi from './'
        // 将组件注册在一个自定义标签上,之后可以在页面中    <Shi></Shi>  这样生成组件中的内容
        export default {
            components: {
                Shi: shi
            },
        }
    </script>



    <!-- 全局组件 :  Vue.component("要全局等级的组件名",引入的组件名)
    在入口文件中引入,可以在所有入口文件中的子级文件调用组件 -->
    语法: 在入口文件中编写如下
    import gonggong from './components/02-gonggong.vue'
    <!-- 组件注册为标签        如此可以调用生成组件 <自定义标签名></自定义标签名>-->
    Vue.component('自定义标签名', gonggong)
    <!-- 组件内样式, 只针对当前组件内标签生效如何做 -->
    在 style 标签中添加 scoped,限制样式生成范围仅限于当前文件
    <style scoped></style>




    <!-- 组件通信       父传子 -->
    用于 vue组件中值的传递

    <!-- 在组件中,
        在需要父级数据的地方写入自定义字符串 -->
    <h3>标题: {{ title }}</h3>
    <p>价格: {{ price }}元</p>
    <p>{{ intro }}</p>
    <!-- props 定义自定义属性,可以用来接收父级传递的数据 -->
    export default {
    props:["title","price","intro","index"],
    }
    <!-- 在父元素中 ,
        1.使用子级组件,并且调用自定义标签
        2.可以 :porps自定义属性="数据" 传递数据--> :title="item"
    <item v-for="(item,index) in list" :key="item.id" :title="item.proname" :price="item.proprice" :intro="item.info"
        :index="index" @xxx="formSon" />









    <!-- 组件通信       子传父-->
    Vue 当子想要去改变父里的数据时,不可以自己直接改变数据,要把要求传递给父级,让父级执行
    <!-- 子级中 -->
    <!-- $emit发送 自定义事件名 和 数据 
        第一个参数为 自定义事件名,之后的所有参数都为传递的参数-->
    methods:{
    this.$emit('自定义事件名', 值)
    }
    <!-- 父级中  
        1. 组件标签内,@自定义事件名="函数名" 
        2. 在函数中可以添加形参,形参会分别对应子级传递过来的数据-->
    <item v-for="(item,index) in list" :key="item.id" :title="item.proname" :price="item.proprice" :intro="item.info"
        :item="item" :index="index" @xxx="formSon" />










    <!-- 组件通信\_跨组件传值 -->
    当2个没有引用关系的组件之间要通信传值,用此方法
    <!-- 1.在入口文件中 声明并创建一个事件总线 -->
    <!-- 把bus挂载到了Vue的原型上, 保证所有的组件都能通过 this.bus访问到事件总线 -->
    const bus = new Vue()
    Vue.prototype.bus = bus
    <!-- 2.发送数据的组件中 -->
    <script>
        methods: {
            fn(){
                // 发布事件：this.bus.$emit('事件名', 额外参数) 
                // 将一个发送的数据发送于   bus 事件总线中,以备其他组件通过事件总线获取数据
                this.bus.$emit("send", this.numb)
            }
        }
    </script>
    <!-- 3.接收数据的组件中 created-->
    <script>
        created(){
            // 订阅事件：bus.$on('事件名', 事件回调函数)
            // 1. 在created中监听 '事件名' 是否在bus发送请求,有则执行接收数据,形参代表传来的数据
            // 2. 回调函数需要写成箭头函数 内部可以是this
            this.bus.$on("send", (e) => {
                console.log(1);
                this.info = e;
            });
        }
    </script>



    <!-- 刷新数据 -->
    $set(重新读取的数组,索引,更改的值)




</template>









vue 第四天总结

<template>
    <!-- Lifecycle -->
    <!-- 生命周期 钩子函数 -->
    <!-- Lifecycle-初始化 -->
    <!-- Vue内部添加data和method数据前 -->
    beforeCreate(){}
    <!-- Vue内部添加data和method数据后 -->
    created(){}


    <!-- Lifecycle-挂载 -->
    <!-- 将 data和method数据 渲染到页面之前 -->
    beforeMount(){}
    <!-- 将 data和method数据 渲染到页面之后 -->
    mounted(){}



    <!-- Lifecycle-更新 -->
    <!-- 数据更新,并同步到页面中 前 -->
    beforeUpdate(){}
    <!-- 数据更新,并同步到页面中 后 -->
    updated(){}





    <!-- Lifecycle-销毁 -->
    <!-- 删除数据之前 -->
    beforeDestroy(){}
    <!-- 删除数据之后 -->
    destroyed(){}




    <!-- vue axios -->
    <script>
        // get请求
        async search(){
            let res = await axios({
                url: "/api/getbooks",
                method: "GET",
                params: {
                    id: 1,
                    bookname: "西游记"
                }
            });
            console.log(res);
        },


        // post请求
        async add(){
            let res = await axios({
                url: "/api/addbook",
                method: "POST",
                data: {
                    bookname: this.bookname,
                    author: this.author,
                    publisher: this.publisher,
                }
            });
            console.log(res);
        }
    </script>



    <!-- vue获取根节点 -->
    this.$el获取根节点 document

    <!-- ref 和 $refs -->
    <p ref="box">我是具有ref的标签</p>
    <script>
        export default {
            // 获取dom元素：
            mounted() {
                // this.$refs.自定义值 获取页面中 ref 值为box的标签和内容
                // 如果写入ref的是一个组件标签,则获取整个组件,配合 $el 可以操作组件内容
                console.log(this.$refs.box);
            }

        }
    </script>






    $nextTick 写在函数中,用于将更改的dom节点 更新打补丁到页面中改变的地方,与updated同理
    <!-- 
        this.$nextTick(()=>{
            console.log(this.$refs.p.innerText);
        }); 
    -->
    1.点击后，数据层发生改变，生成一份新的虚拟dom节点；
    2.通过diff算法，找到差异的部分，打补丁到真实dom节点上；
    3.打补丁到真实dom节点上：是异步；

</template>













vue 第五天总结

<body>
    <!-- 动态组件   vueTAB栏切换-->
    多个组件使用同一个挂载点，并动态切换，这就是动态组件
    1.将两个切换显示的组件引入到app文件
    2.通过 component:{} 声明完毕后
    3.在html部分 书写: <component is='显示的组件自定义标签名'></component>标签
    4.在 is 中可以以变量形式进行控制展示不同的组件
    <component is='显示的组件自定义标签名'></component>




    <!-- 组件缓存 -->
    keep-alive
    Vue内置keep-alive组件, 把标签包起来的组件缓存起来,包括存在过的所有组件信息
    <keep-alive>
        <component :is="name"></component>
    </keep-alive>






    <!-- 匿名插槽 -->
    vue提供组件插槽能力, 允许开发者在封装组件时，把不确定的部分定义为插槽
    即同一个组件生成不同的结构用以替换组件中的部分

    组件中被替换以:<slot></slot>为范围
    <slot>这里是被替换的部分,如果父级没有定义替换,则显示这个标签内的文字</slot>

    父级文件中,
    <组件自定义标签>中间写的内容就是用来替换此组件中 slot 中的结构内容</组件自定义标签>




    <!-- 多个插槽 具名插槽 -->
    当组件中有多个部分需要替换,则使用具名插槽
    具名插槽 v-slot:name名字 可以用 #name名字 简写
    在 slot 标签中设置 name 属性,用以父级中选中替换的部分   
    <slot name="place1">默认显示1</slot>
    <slot name="place2">默认显示2</slot>

    父级中, 在标签内添加一个 <template></template> 标签,用以查询 slot name的 标识
    v-slot:place2 冒号后边的就是查询的 name 属性
    <组件自定义标签>
        <template v-slot:place2>
            这里写插入的结构
        </template>
    </组件自定义标签>





    <!-- 作用域插槽 -->
    将组件中的数据传递给父级,
    :接收的数据名='传递的数据'
    <slot :obj="obj">
        <p>{{obj.msg1}}</p>
        <p>{{obj.msg1}}</p>
    </slot>

    父级中,<template></template>标签中, v-slot='接收的数据名'
    <组件自定义标签>
        <template v-slot="getSon">
            <h3>{{getSon.obj.msg2}}</h3>
            <h3>{{getSon.obj.msg2}}</h3>
            <h3>{{getSon.obj.msg2}}</h3>
            <h3>{{getSon.obj.msg2}}</h3>
        </template>
    </组件自定义标签>








    <!-- 自定义指令 --> Vue.directive
    <!-- 
        // inserted方法 - 指令所在标签, 被插入到网页上触发(一次)
        // update 方法 - 指令对应数据/标签更新时, 此方法执行 
    -->
    <!-- 局部指令 -->
    <script>
        export default {
            directives: {
                // v-自定义指令名称：v-aaa
                aaa: {
                    // inserted 虚拟dom第一次渲染到页面是成为真实dom节点 执行
                    inserted(el) {
                        //   el: 对使用该指令 真实dom节点
                        el.focus();
                    },
                    // update 自定义指令对应 数据/标签 更新时, 此方法执行
                    update(el, obj) {
                        //   el: 对使用该指令 真实dom节点
                        //   obj：传入的数据对象，里面可以获取传入的数据值
                        el.style.width = 100 + obj.value + "px";
                    },
                },
            },
        }
    </script>



    <!-- 全局指令  -->
    在入口文件中书写,全局加上 v-bgc 就可以调用
    <!-- 背景颜色随机变 -->
    <script>
        Vue.directive("bgc", {
            inserted(el) {
                let a = () => Math.floor(Math.random() * 256);
                el.style.backgroundColor = `rgb(${a()},${a()},${a()})`;
                // 拓展：给dom注册事件 
            },
        });
    </script>


</body>












vue 第六天总结


<body>
    <script>
        // 路由
        // 下载模块 yarn add vue-router -S
        import VueRouter from 'vue-router'
        Vue.use(VueRouter);
        // 入口文件中定义路由的路径
        const routes = [
            // 默认打开的时候。自动显示 #/   ----->根据配置自动来到我们定义好路由
            {
                // 重定向
                path: "/",
                // ?参数的话  哪怕下面规定了路由参数，重定向不成功！注意！   redirect: "/my?name=cc"
                redirect: "/find"
            },
            {// 配置的是一级路径 
                path: "/find", // 设计的路径，不是vue文件真实的路径！
                component: Find,
                children: [{ // 二级路径
                    path: "toplist", // 路由名称随便定义 前面没有/
                    component: FindToplist,
                },
                {
                    path: "playlist", // 路由名称随便定义
                    component: FindPlaylist,
                },
                {
                    path: "djradio", // 路由名称随便定义
                    component: FindDjradio,
                },
                ]
            },
            {   // 设置传值格式
                path: '/find/:id',
                component: My
            },
            { //  404 跳转
                path: "*",
                component: NotFound
            }
        ];


        const router = new VueRouter({
            routes,
            // 模式设置
            // mode: 'history'                   
        })  // 之后把 router 添加到 new Vue 中


        // 强制跳转
        const isLogin = false
        router.beforeEach((to, from, next) => {
            if (to.path == '/my' && isLogin == false) {
                next('/login')
            } else {
                next()
            }
        })



            // 父文件中 引入路由
            < a href = "#/find" > 发现音乐</a >
        // 或   <router-link to=''></router-link>
        // 这种形式会将路由以a链接形式进行输出,并自带一个类名以便设置 tab 栏切换样式
        //     公共类名:     .router-link-active
        <router-link to="/find">发现音乐</router-link>

        // 父文件中 以<router-view></router-view>标签显示引入的路由
        <router-view></router-view>



        // 二级路由     书写入口文件中定义的二级路由路径
        <router-link to="/find/toplist">排行榜</router-link>



        // 跳转传参
        // 两种读取传值的方式
        { { $route.query.id } }     //   /my?name=zs 
        //   /my/cc 



        // 路由传值 
        // /one/:id

        // 好理解的方法
        this.$router.push({
            path: "/one/" + id
        });

        // params官方:
        this.$router.push({
            name: "one",
            params: {
                id: id
            }
        });

        // /one?id=1
        // query官方：
        this.$router.push({
            path: "/one",
            query: {
                // 参数名：形参
                id: id,
            },
        });



        // Vant框架
        // .自动按需引入    
        // yarn add babel-plugin-import -D

        // 在 babel.config.js 文件中设置如下
        module.exports = {
            plugins: [
                ['import', {
                    libraryName: 'vant',
                    libraryDirectory: 'es',
                    style: true
                }, 'vant']
            ]
        };
        // 入口文件中按需写入
        import { Button } from 'vant';
        Vue.use(Button);
        // 然后 CV 大法好







    </script>

</body>








vue 黑马头条 // vuex

<body>
    <script>
        // vuex
        // 下载
        // yarn add vuex -S


        // 引入
        import Vue from 'vue'
        import Vuex from 'vuex'

        Vue.use(Vuex)// 给组件 添加 $store 



        1. state、getters 都是 映射 在 组件 的 computed 中
        2. mutations、actions  都是 映射 在 组件 的 methods 中



        // state   的调用
        // 直接调用
        this.$store.state.变量名
        // 映射使用
        import { mapState } from 'vuex'
        export default {
            computed: {
                ...mapState(['state变量名']),// 不能改名
                ...mapState({ // 能改名
                    留在原地计算属性名: 'state中变量名'
                })
            }
        }

        // mutations    的使用
        // 直接调用
        this.$store.commit('mutations中的函数名', 传值)
        // 映射使用
        import { mapMutations } from 'vuex'
        export default {
            methods: {
                ...mapMutations(['mutations中函数名'])
            }
        }


        // actions  的使用
        // 直接调用
        this.$store.dispatch('actions中的函数名', 传值)
        // 映射使用
        import { mapActions } from 'vuex'
        export default {
            methods: {
                ...mapActions(['actions函数名'])
            }
        }

        // getters  的使用
        // 直接调用
        this.$store.getters.计算属性的名字
        // 映射使用
        import { mapGetters } from 'vuex'
        export default {
            computed: {
                ...mapGetters(['getters中计算属性的名字'])
            }
        }


        // 注册vuex  公共资源
        const store = new Vuex.Store({
            // state:   储存共享的数据源,仅可以被 mutations 更改
            state: {
                key: value
            },
            // mutations:  同步函数,`唯一` 可以 `同步` 修改 state的 地方
            mutations: {
                fn() { }
            },
            // actions: 异步函数,异步 的 修改 state，但其不能直接改，最终必须 commit 到 指定 mutations 中
            actions: {
                fn2() { }
            },
            // getters: vuex 的计算属性,数据源 计算而得到，类似computed、优势带缓存
            getters: {
                fn3() {
                    return
                }
            }
        })







        // 分模块   调用方法
        // state
        this.$store.state.模块名.变量名
        ...mapState("模块名", ['变量名'])
        // mutations
        this.$store.commit("模块名/mutations里的函数名", 具体值)
        ...mapMutations("模块名", ['mutations里方法名'])
        // actions
        this.$store.dispatch("模块名/actions里的函数名", 具体值)
        ...mapActions("模块名", ['actions里方法名'])
        // getters
        this.$store.getters['模块名/计算属性名']
        ...mapGetters("模块名", ['getters里计算属性名'])



        export default store

    </script>
</body>



</html>